-
Notifications
You must be signed in to change notification settings - Fork 467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#30277 API/Factory methods to insert in the unique_fields table #30332
Closed
freddyDOTCMS
wants to merge
29
commits into
main
from
issue-30277-Create-API-Factory-methods-to-insert-in-the-unique_fields-table
Closed
Changes from 13 commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
e0e83bd
bug(apps) fixing link to dotAI portlet (#29556)
wezell 5fff6b7
#30277 API/Factory methods to insert in the unique_fields table
freddyDOTCMS 8a61eaa
#30277 Javadoc
freddyDOTCMS 59ce98b
Merge branch 'main' into issue-30277-Create-API-Factory-methods-to-in…
freddyDOTCMS 4fcf5a7
#30306 Fixing test
freddyDOTCMS 64d7a0e
Merge branch 'main' into issue-30277-Create-API-Factory-methods-to-in…
freddyDOTCMS 23b73e5
Adding MainSuite
freddyDOTCMS 28e0e04
Merge branch 'issue-30277-Create-API-Factory-methods-to-insert-in-the…
freddyDOTCMS 5d0574a
Missing changes
freddyDOTCMS 0403905
Merge branch 'main' into issue-30277-Create-API-Factory-methods-to-in…
freddyDOTCMS f17ca69
Merge branch 'main' into issue-30277-Create-API-Factory-methods-to-in…
freddyDOTCMS 504efaa
#30277 Feedback
freddyDOTCMS 0f40ac6
Merge branch 'issue-30277-Create-API-Factory-methods-to-insert-in-the…
freddyDOTCMS bc8ee9f
#30277 Feedback
freddyDOTCMS a19069c
#302077 Including CDI
freddyDOTCMS 3c7fa5c
#302077 Renamong to API
freddyDOTCMS 0aa9ced
feedback
freddyDOTCMS abb53a6
Merge branch 'main' into issue-30277-Create-API-Factory-methods-to-in…
freddyDOTCMS 93f59f9
#30277 Create Strategy classes
freddyDOTCMS 126c4ee
#30277 Validate when a Contentlet is Updated o saved
freddyDOTCMS df2e213
merge
freddyDOTCMS 4069133
#30279 Fixing test
freddyDOTCMS 7330a78
#30279 Fixing test
freddyDOTCMS 9f50a0f
Merge remote-tracking branch 'origin/master' into issue-30277-Create-…
freddyDOTCMS 5bdcb6e
merge
freddyDOTCMS 1f4a1b1
Fixing test
freddyDOTCMS 7381cc9
Merge branch 'main' into issue-30277-Create-API-Factory-methods-to-in…
freddyDOTCMS 0d0fe1b
Removing unneeded changes
freddyDOTCMS 555b48d
Merge branch 'issue-30277-Create-API-Factory-methods-to-insert-in-the…
freddyDOTCMS File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
144 changes: 144 additions & 0 deletions
144
dotCMS/src/main/java/com/dotcms/contenttype/business/UniqueFieldCriteria.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
package com.dotcms.contenttype.business; | ||
|
||
import com.dotcms.content.elasticsearch.business.ESContentletAPIImpl; | ||
import com.dotcms.contenttype.model.field.Field; | ||
import com.dotcms.contenttype.model.type.ContentType; | ||
import com.dotmarketing.beans.Host; | ||
import com.dotmarketing.business.APILocator; | ||
import com.dotmarketing.exception.DotDataException; | ||
import com.dotmarketing.exception.DotRuntimeException; | ||
import com.dotmarketing.portlets.languagesmanager.model.Language; | ||
import com.dotmarketing.util.StringUtils; | ||
import com.liferay.util.StringPool; | ||
|
||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
/** | ||
* Represent the criteria used to determine if a value is unique or not | ||
*/ | ||
public class UniqueFieldCriteria { | ||
private final ContentType contentType; | ||
private final Field field; | ||
private final Object value; | ||
private final Language language; | ||
private final Host site; | ||
|
||
public UniqueFieldCriteria(final Builder builder) { | ||
this.contentType = builder.contentType; | ||
this.field = builder.field; | ||
this.value = builder.value; | ||
this.language = builder.language; | ||
this.site = builder.site; | ||
} | ||
|
||
/** | ||
* Return a Map with the values in this Unique Field Criteria | ||
* @return | ||
*/ | ||
public Map<String, Object> toMap(){ | ||
return Map.of( | ||
"contentTypeID", Objects.requireNonNull(contentType.id()), | ||
"fieldVariableName", Objects.requireNonNull(field.variable()), | ||
"fieldValue", value.toString(), | ||
"languageId", language.getId(), | ||
"hostId", site.getIdentifier(), | ||
"uniquePerSite", isUniqueForSite(contentType.id(), field.variable()) | ||
); | ||
} | ||
|
||
/** | ||
* return true if the uniquePerSite Field Variable is set to true. | ||
* | ||
* @param contentTypeId | ||
* @param fieldVariableName | ||
* @return | ||
*/ | ||
private static boolean isUniqueForSite(String contentTypeId, String fieldVariableName) { | ||
try { | ||
final Field uniqueField = APILocator.getContentTypeFieldAPI().byContentTypeIdAndVar(contentTypeId, fieldVariableName); | ||
|
||
return uniqueField.fieldVariableValue(ESContentletAPIImpl.UNIQUE_PER_SITE_FIELD_VARIABLE_NAME) | ||
.map(Boolean::valueOf).orElse(false); | ||
} catch (DotDataException e) { | ||
throw new DotRuntimeException(e); | ||
} | ||
} | ||
|
||
/** | ||
* Return a hash calculated as follow: | ||
* | ||
* - If the uniquePerSite Field Variable is set to true then concat the: | ||
* Content Type' id + Field Variable Name + Language's Id + Field Value | ||
* | ||
* - If the uniquePerSite Field Variable is set to false then concat the: | ||
* Content Type' id + Field Variable Name + Language's Id + Field Value + Site's id | ||
* | ||
* @return | ||
*/ | ||
public String hash(){ | ||
return StringUtils.hashText(contentType.id() + field.variable() + language.getId() + value + | ||
((isUniqueForSite(contentType.id(), field.variable())) ? site.getIdentifier() : StringPool.BLANK)); | ||
} | ||
|
||
public Field field() { | ||
return field; | ||
} | ||
|
||
public Object value() { | ||
return value; | ||
} | ||
|
||
public ContentType contentType() { | ||
return contentType; | ||
} | ||
|
||
public Language language() { | ||
return language; | ||
} | ||
|
||
|
||
public static class Builder { | ||
private ContentType contentType; | ||
private Field field; | ||
private Object value; | ||
private Language language; | ||
private Host site; | ||
|
||
|
||
public Builder setContentType(final ContentType contentType) { | ||
this.contentType = contentType; | ||
return this; | ||
} | ||
|
||
public Builder setField(final Field field) { | ||
this.field = field; | ||
return this; | ||
} | ||
|
||
public Builder setValue(final Object value) { | ||
this.value = value; | ||
return this; | ||
} | ||
|
||
public Builder setLanguage(final Language language) { | ||
this.language = language; | ||
return this; | ||
} | ||
|
||
public Builder setSite(final Host site) { | ||
this.site = site; | ||
return this; | ||
} | ||
|
||
public UniqueFieldCriteria build(){ | ||
Objects.requireNonNull(contentType); | ||
Objects.requireNonNull(field); | ||
Objects.requireNonNull(value); | ||
Objects.requireNonNull(language); | ||
Objects.requireNonNull(site); | ||
|
||
return new UniqueFieldCriteria(this); | ||
} | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
dotCMS/src/main/java/com/dotcms/contenttype/business/UniqueFieldFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.dotcms.contenttype.business; | ||
|
||
import com.dotmarketing.exception.DotDataException; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* This Factory allow you to interact with the unique_fields table | ||
*/ | ||
public interface UniqueFieldFactory { | ||
|
||
/** | ||
* Insert a new register into the unique_fields table, if already exists another register with the same | ||
* 'unique_key_val' then a {@link java.sql.SQLException} is thrown. | ||
* | ||
* @param key | ||
* @param supportingValues | ||
*/ | ||
void insert(final String key, final Map<String, Object> supportingValues) throws DotDataException; | ||
} |
24 changes: 24 additions & 0 deletions
24
dotCMS/src/main/java/com/dotcms/contenttype/business/UniqueFieldFactoryImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.dotcms.contenttype.business; | ||
|
||
import com.dotmarketing.common.db.DotConnect; | ||
import com.dotmarketing.exception.DotDataException; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* Default implementation of {@link UniqueFieldFactory} | ||
*/ | ||
public class UniqueFieldFactoryImpl implements UniqueFieldFactory { | ||
|
||
private final static String INSERT_SQL = "INSERT INTO unique_fields (unique_key_val, supporting_values) VALUES (?, ?)"; | ||
/** | ||
* Default implementation of {@link UniqueFieldFactory#insert(String, Map)} | ||
* | ||
* @param key | ||
* @param supportingValues | ||
*/ | ||
@Override | ||
public void insert(final String key, final Map<String, Object> supportingValues) throws DotDataException { | ||
new DotConnect().setSQL(INSERT_SQL).addParam(key).addJSONParam(supportingValues).loadObjectResults(); | ||
} | ||
} |
77 changes: 77 additions & 0 deletions
77
dotCMS/src/main/java/com/dotcms/contenttype/business/UniqueFieldUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package com.dotcms.contenttype.business; | ||
|
||
import com.dotcms.business.WrapInTransaction; | ||
import com.dotcms.content.elasticsearch.business.ESContentletAPIImpl; | ||
import com.dotcms.util.CollectionsUtils; | ||
import com.dotmarketing.business.FactoryLocator; | ||
import com.dotmarketing.exception.DotDataException; | ||
import com.dotmarketing.util.Logger; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
/** | ||
* This Helper allow you to interact with the unique_fields table | ||
*/ | ||
class UniqueFieldUtil { | ||
|
||
private final UniqueFieldFactory uniqueFieldFactory; | ||
|
||
public UniqueFieldUtil(){ | ||
this(FactoryLocator.getUniqueFieldFactory()); | ||
} | ||
|
||
public UniqueFieldUtil(final UniqueFieldFactory uniqueFieldFactory) { | ||
this.uniqueFieldFactory = uniqueFieldFactory; | ||
} | ||
|
||
|
||
/** | ||
* Insert a new unique field value, if the value is duplicated then a {@link java.sql.SQLException} is thrown. | ||
* | ||
* @param uniqueFieldCriteria | ||
* @param contentletId | ||
* | ||
* @throws UniqueFieldValueDupliacatedException when the Value is duplicated | ||
* @throws DotDataException when a DotDataException is throws | ||
*/ | ||
@WrapInTransaction | ||
public void insert(final UniqueFieldCriteria uniqueFieldCriteria, final String contentletId) | ||
throws UniqueFieldValueDupliacatedException, DotDataException { | ||
|
||
if (!uniqueFieldCriteria.field().unique()) { | ||
final String message = String.format("The Field %s is not unique", uniqueFieldCriteria.field().variable()); | ||
Logger.debug(UniqueFieldUtil.class, message); | ||
throw new IllegalArgumentException(message); | ||
} | ||
|
||
final boolean uniqueForSite = uniqueFieldCriteria.field().fieldVariableValue(ESContentletAPIImpl.UNIQUE_PER_SITE_FIELD_VARIABLE_NAME) | ||
.map(Boolean::valueOf).orElse(false); | ||
|
||
final Map<String, Object> supportingValues = new HashMap<>(uniqueFieldCriteria.toMap()); | ||
supportingValues.put("contentletsId", CollectionsUtils.list(contentletId)); | ||
supportingValues.put("uniquePerSite", uniqueForSite); | ||
|
||
try { | ||
Logger.debug(UniqueFieldUtil.class, "Including value in the unique_fields table"); | ||
uniqueFieldFactory.insert(uniqueFieldCriteria.hash(), supportingValues); | ||
} catch (DotDataException e) { | ||
|
||
if (isDuplicatedKeyError(e)) { | ||
final String duplicatedValueMessage = String.format("The value %s for the field %s in the Content type %s is duplicated", | ||
uniqueFieldCriteria.value(), uniqueFieldCriteria.field().variable(), | ||
uniqueFieldCriteria.contentType().variable()); | ||
|
||
Logger.error(UniqueFieldUtil.class, duplicatedValueMessage); | ||
throw new UniqueFieldValueDupliacatedException(duplicatedValueMessage); | ||
} | ||
} | ||
} | ||
|
||
private static boolean isDuplicatedKeyError(final Exception exeption) { | ||
final String originalMessage = exeption.getMessage(); | ||
|
||
return originalMessage != null && originalMessage.startsWith( | ||
"ERROR: duplicate key value violates unique constraint \"unique_fields_pkey\""); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
...S/src/main/java/com/dotcms/contenttype/business/UniqueFieldValueDupliacatedException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.dotcms.contenttype.business; | ||
|
||
/** | ||
* Throw if try to insert a duplicated register in unique_fiedls table | ||
*/ | ||
public class UniqueFieldValueDupliacatedException extends Exception{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done 0aa9ced |
||
|
||
public UniqueFieldValueDupliacatedException(String message) { | ||
super(message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the factory concept usually is next to an API, since you do not have any, and there are not any plans of covering more general cases, this is just a single line you may move straight to the Helper/API you have
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think is better kepp the Factory because I am going to include more SQL Statement here later