From 6b1a4cc7328b900cf016d76d0b310eb1d8215b15 Mon Sep 17 00:00:00 2001 From: Aron Roberts Date: Tue, 10 Jul 2012 14:26:15 -0700 Subject: [PATCH] CSPACE-5359: Cleanup to improve clarity of program flow, variable naming, log statements. --- .../vocabulary/RefNameServiceUtils.java | 972 +++++++++--------- 1 file changed, 489 insertions(+), 483 deletions(-) diff --git a/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java b/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java index 17f35a645..009605de2 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java @@ -1,25 +1,24 @@ /** - * This document is a part of the source code and related artifacts - * for CollectionSpace, an open source collections management system - * for museums and related institutions: - - * http://www.collectionspace.org - * http://wiki.collectionspace.org - - * Copyright 2009 University of California at Berkeley - - * Licensed under the Educational Community License (ECL), Version 2.0. - * You may not use this file except in compliance with this License. - - * You may obtain a copy of the ECL 2.0 License at - - * https://source.collectionspace.org/collection-space/LICENSE.txt - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * This document is a part of the source code and related artifacts for + * CollectionSpace, an open source collections management system for museums and + * related institutions: + * + * http://www.collectionspace.org http://wiki.collectionspace.org + * + * Copyright 2009 University of California at Berkeley + * + * Licensed under the Educational Community License (ECL), Version 2.0. You may + * not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. */ package org.collectionspace.services.common.vocabulary; @@ -70,282 +69,314 @@ import org.collectionspace.services.nuxeo.util.NuxeoUtils; import com.sun.xml.bind.v2.runtime.unmarshaller.XsiNilLoader.Array; /** - * RefNameServiceUtils is a collection of services utilities related to refName usage. + * RefNameServiceUtils is a collection of services utilities related to refName + * usage. * - * $LastChangedRevision: $ - * $LastChangedDate: $ + * $LastChangedRevision: $ $LastChangedDate: $ */ public class RefNameServiceUtils { - public static class AuthRefConfigInfo { - public String getQualifiedDisplayName() { - return(Tools.isBlank(schema))? - displayName:DocumentUtils.appendSchemaName(schema, displayName); - } - public String getDisplayName() { - return displayName; - } - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - String displayName; - String schema; - public String getSchema() { - return schema; - } - public void setSchema(String schema) { - this.schema = schema; - } - public String getFullPath() { - return fullPath; - } - public void setFullPath(String fullPath) { - this.fullPath = fullPath; - } - String fullPath; - protected String[] pathEls; - public AuthRefConfigInfo(AuthRefConfigInfo arci) { - this.displayName = arci.displayName; - this.schema = arci.schema; - this.fullPath = arci.fullPath; - this.pathEls = arci.pathEls; - // Skip the pathElse check, since we are creatign from another (presumably valid) arci. - } - - public AuthRefConfigInfo(String displayName, String schema, String fullPath, String[] pathEls) { - this.displayName = displayName; - this.schema = schema; - this.fullPath = fullPath; - this.pathEls = pathEls; - checkPathEls(); - } - - // Split a config value string like "intakes_common:collector", or - // "collectionobjects_common:contentPeoples|contentPeople" - // "collectionobjects_common:assocEventGroupList/*/assocEventPlace" - // If has a pipe ('|') second part is a displayLabel, and first is path - // Otherwise, entry is a path, and can use the last pathElement as displayName - // Should be schema qualified. - public AuthRefConfigInfo(String configString) { - String[] pair = configString.split("\\|", 2); - String[] pathEls; - String displayName, fullPath; - if(pair.length == 1) { - // no label specifier, so we'll defer getting label - fullPath = pair[0]; - pathEls = pair[0].split("/"); - displayName = pathEls[pathEls.length-1]; - } else { - fullPath = pair[0]; - pathEls = pair[0].split("/"); - displayName = pair[1]; - } - String[] schemaSplit = pathEls[0].split(":",2); - String schema; - if(schemaSplit.length==1) { // schema not specified - schema = null; - } else { - schema = schemaSplit[0]; - if(pair.length == 1 && pathEls.length == 1) { // simplest case of field in top level schema, no labelll - displayName = schemaSplit[1]; // Have to fix up displayName to have no schema - } - } - this.displayName = displayName; - this.schema = schema; - this.fullPath = fullPath; - this.pathEls = pathEls; - checkPathEls(); - } - - protected void checkPathEls() { - int len = pathEls.length; - if(len<1) - throw new InternalError("Bad values in authRef info - caller screwed up:"+fullPath); - // Handle case of them putting a leading slash on the path - if(len>1 && pathEls[0].endsWith(":")) { - len--; - String[] newArray = new String[len]; - newArray[0] = pathEls[0]+pathEls[1]; - if(len>=2) { - System.arraycopy(pathEls, 2, newArray, 1, len-1); - } - pathEls = newArray; - } - } - } - - public static class AuthRefInfo extends AuthRefConfigInfo { - public Property getProperty() { - return property; - } - public void setProperty(Property property) { - this.property = property; - } - Property property; - public AuthRefInfo(String displayName, String schema, String fullPath, String[] pathEls, Property prop) { - super(displayName, schema, fullPath, pathEls); - this.property = prop; - } - public AuthRefInfo(AuthRefConfigInfo arci, Property prop) { - super(arci); - this.property = prop; - } - } + public static class AuthRefConfigInfo { + + public String getQualifiedDisplayName() { + return (Tools.isBlank(schema)) + ? displayName : DocumentUtils.appendSchemaName(schema, displayName); + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + String displayName; + String schema; + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + + public String getFullPath() { + return fullPath; + } + + public void setFullPath(String fullPath) { + this.fullPath = fullPath; + } + String fullPath; + protected String[] pathEls; + + public AuthRefConfigInfo(AuthRefConfigInfo arci) { + this.displayName = arci.displayName; + this.schema = arci.schema; + this.fullPath = arci.fullPath; + this.pathEls = arci.pathEls; + // Skip the pathElse check, since we are creatign from another (presumably valid) arci. + } + + public AuthRefConfigInfo(String displayName, String schema, String fullPath, String[] pathEls) { + this.displayName = displayName; + this.schema = schema; + this.fullPath = fullPath; + this.pathEls = pathEls; + checkPathEls(); + } + + // Split a config value string like "intakes_common:collector", or + // "collectionobjects_common:contentPeoples|contentPeople" + // "collectionobjects_common:assocEventGroupList/*/assocEventPlace" + // If has a pipe ('|') second part is a displayLabel, and first is path + // Otherwise, entry is a path, and can use the last pathElement as displayName + // Should be schema qualified. + public AuthRefConfigInfo(String configString) { + String[] pair = configString.split("\\|", 2); + String[] pathEls; + String displayName, fullPath; + if (pair.length == 1) { + // no label specifier, so we'll defer getting label + fullPath = pair[0]; + pathEls = pair[0].split("/"); + displayName = pathEls[pathEls.length - 1]; + } else { + fullPath = pair[0]; + pathEls = pair[0].split("/"); + displayName = pair[1]; + } + String[] schemaSplit = pathEls[0].split(":", 2); + String schema; + if (schemaSplit.length == 1) { // schema not specified + schema = null; + } else { + schema = schemaSplit[0]; + if (pair.length == 1 && pathEls.length == 1) { // simplest case of field in top level schema, no labelll + displayName = schemaSplit[1]; // Have to fix up displayName to have no schema + } + } + this.displayName = displayName; + this.schema = schema; + this.fullPath = fullPath; + this.pathEls = pathEls; + checkPathEls(); + } + + protected void checkPathEls() { + int len = pathEls.length; + if (len < 1) { + throw new InternalError("Bad values in authRef info - caller screwed up:" + fullPath); + } + // Handle case of them putting a leading slash on the path + if (len > 1 && pathEls[0].endsWith(":")) { + len--; + String[] newArray = new String[len]; + newArray[0] = pathEls[0] + pathEls[1]; + if (len >= 2) { + System.arraycopy(pathEls, 2, newArray, 1, len - 1); + } + pathEls = newArray; + } + } + } + + public static class AuthRefInfo extends AuthRefConfigInfo { + + public Property getProperty() { + return property; + } + + public void setProperty(Property property) { + this.property = property; + } + Property property; + + public AuthRefInfo(String displayName, String schema, String fullPath, String[] pathEls, Property prop) { + super(displayName, schema, fullPath, pathEls); + this.property = prop; + } + public AuthRefInfo(AuthRefConfigInfo arci, Property prop) { + super(arci); + this.property = prop; + } + } private static final Logger logger = LoggerFactory.getLogger(RefNameServiceUtils.class); - private static ArrayList refNameServiceTypes = null; - + public static List getConfiguredAuthorityRefs(ServiceContext ctx) { - List authRefFields = + List authRefFields = ((AbstractServiceContextImpl) ctx).getAllPartsPropertyValues( ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES); - ArrayList authRefsInfo = new ArrayList(authRefFields.size()); - for(String spec:authRefFields) { - AuthRefConfigInfo arci = new AuthRefConfigInfo(spec); - authRefsInfo.add(arci); - } - return authRefsInfo; + ArrayList authRefsInfo = new ArrayList(authRefFields.size()); + for (String spec : authRefFields) { + AuthRefConfigInfo arci = new AuthRefConfigInfo(spec); + authRefsInfo.add(arci); + } + return authRefsInfo; } public static AuthorityRefDocList getAuthorityRefDocs( - RepositoryInstance repoSession, - ServiceContext ctx, + RepositoryInstance repoSession, + ServiceContext ctx, RepositoryClient repoClient, List serviceTypes, String refName, String refPropName, DocumentFilter filter, boolean computeTotal) - throws DocumentException, DocumentNotFoundException { - AuthorityRefDocList wrapperList = new AuthorityRefDocList(); + throws DocumentException, DocumentNotFoundException { + AuthorityRefDocList wrapperList = new AuthorityRefDocList(); AbstractCommonList commonList = (AbstractCommonList) wrapperList; int pageNum = filter.getStartPage(); - int pageSize = filter.getPageSize(); + int pageSize = filter.getPageSize(); commonList.setPageNum(pageNum); commonList.setPageSize(pageSize); List list = wrapperList.getAuthorityRefDocItem(); - + Map queriedServiceBindings = new HashMap(); Map> authRefFieldsByService = new HashMap>(); - RepositoryJavaClientImpl nuxeoRepoClient = (RepositoryJavaClientImpl)repoClient; - try { - DocumentModelList docList = findAuthorityRefDocs(ctx, repoClient, repoSession, - serviceTypes, refName, refPropName, queriedServiceBindings, authRefFieldsByService, - filter.getWhereClause(), pageSize, pageNum, computeTotal); - - if (docList == null) { // found no authRef fields - nothing to process - return wrapperList; - } - // Set num of items in list. this is useful to our testing framework. - commonList.setItemsInPage(docList.size()); - // set the total result size - commonList.setTotalItems(docList.totalSize()); - // set the fieldsReturned list. Even though this is a fixed schema, app layer treats - // this like other abstract common lists - /* - - - - - - - - - */ - String fieldList = "docType|docId|docNumber|docName|sourceField|uri|updatedAt|workflowState"; - commonList.setFieldsReturned(fieldList); - - int nRefsFound = processRefObjsDocList(docList, refName, queriedServiceBindings, authRefFieldsByService, // the actual list size needs to be updated to the size of "list" - list, null); - if(logger.isDebugEnabled() && (nRefsFound < docList.size())) { - logger.debug("Internal curiosity: got fewer matches of refs than # docs matched..."); // We found a ref to ourself and have excluded it. - } - } catch (Exception e) { - logger.error("Could not retrieve the Nuxeo repository", e); - wrapperList = null; - } - - return wrapperList; + RepositoryJavaClientImpl nuxeoRepoClient = (RepositoryJavaClientImpl) repoClient; + try { + DocumentModelList docList = findAuthorityRefDocs(ctx, repoClient, repoSession, + serviceTypes, refName, refPropName, queriedServiceBindings, authRefFieldsByService, + filter.getWhereClause(), null, pageSize, pageNum, computeTotal); + + if (docList == null) { // found no authRef fields - nothing to process + return wrapperList; + } + // Set num of items in list. this is useful to our testing framework. + commonList.setItemsInPage(docList.size()); + // set the total result size + commonList.setTotalItems(docList.totalSize()); + // set the fieldsReturned list. Even though this is a fixed schema, app layer treats + // this like other abstract common lists + /* + * + * + * + * + * + * + * + * + */ + String fieldList = "docType|docId|docNumber|docName|sourceField|uri|updatedAt|workflowState"; + commonList.setFieldsReturned(fieldList); + + int nRefsFound = processRefObjsDocList(docList, refName, queriedServiceBindings, authRefFieldsByService, // the actual list size needs to be updated to the size of "list" + list, null); + if (logger.isDebugEnabled() && (nRefsFound < docList.size())) { + logger.debug("Internal curiosity: got fewer matches of refs than # docs matched..."); // We found a ref to ourself and have excluded it. + } + } catch (Exception e) { + logger.error("Could not retrieve the Nuxeo repository", e); + wrapperList = null; + } + + return wrapperList; } - + private static ArrayList getRefNameServiceTypes() { - if(refNameServiceTypes == null) { - refNameServiceTypes = new ArrayList(); - refNameServiceTypes.add(ServiceBindingUtils.SERVICE_TYPE_AUTHORITY); - refNameServiceTypes.add(ServiceBindingUtils.SERVICE_TYPE_OBJECT); - refNameServiceTypes.add(ServiceBindingUtils.SERVICE_TYPE_PROCEDURE); - } - return refNameServiceTypes; + if (refNameServiceTypes == null) { + refNameServiceTypes = new ArrayList(); + refNameServiceTypes.add(ServiceBindingUtils.SERVICE_TYPE_AUTHORITY); + refNameServiceTypes.add(ServiceBindingUtils.SERVICE_TYPE_OBJECT); + refNameServiceTypes.add(ServiceBindingUtils.SERVICE_TYPE_PROCEDURE); + } + return refNameServiceTypes; } - // Seems like a good value - no real data to set this well. - private static final int N_OBJS_TO_UPDATE_PER_LOOP = 100; - + // private static final int N_OBJS_TO_UPDATE_PER_LOOP = 100; + // FIXME: This value is set to 3 during debugging; needs to be set higher during production - ADR 2012-07-10 + private static final int N_OBJS_TO_UPDATE_PER_LOOP = 3; + public static int updateAuthorityRefDocs( - ServiceContext ctx, + ServiceContext ctx, RepositoryClient repoClient, RepositoryInstance repoSession, String oldRefName, String newRefName, - String refPropName ) throws Exception { + String refPropName) throws Exception { Map queriedServiceBindings = new HashMap(); Map> authRefFieldsByService = new HashMap>(); + + int docsScanned = 0; int nRefsFound = 0; - if(!(repoClient instanceof RepositoryJavaClientImpl)) { - throw new InternalError("updateAuthorityRefDocs() called with unknown repoClient type!"); - } - try { // REM - How can we deal with transaction and timeout issues hear. - final int pageSize = N_OBJS_TO_UPDATE_PER_LOOP; // Set a limit of num of objects -something like 1000K objects and also add a log Warning after some threshold - int pageNumProcessed = 1; - while(true) { // Keep looping until we find all the refs. - logger.debug("updateAuthorityRefDocs working on page: "+pageNumProcessed); - // Note that we always ask the Repo for the first page, since each page we process - // should not be found in successive searches. Slightly inefficient, but more - // reliable (stateless). - DocumentModelList docList = findAuthorityRefDocs(ctx, repoClient, repoSession, //is there an orderBy clause? set the orderby clause to something non-transient like createAt - getRefNameServiceTypes(), oldRefName, refPropName, - queriedServiceBindings, authRefFieldsByService, null, pageSize, 0, false /*don't compute total*/); //loop through the pages until we're finished -i.e., don't just keep getting the first page - - if((docList == null) // found no authRef fields - nothing to do - || (docList.size() == 0)) { // No more to handle - logger.debug("updateAuthorityRefDocs no more results"); - break; - } - logger.debug("updateAuthorityRefDocs curr page result list size: "+docList.size()); - int nRefsFoundThisPage = processRefObjsDocList(docList, oldRefName, queriedServiceBindings, authRefFieldsByService, - null, newRefName); - if(nRefsFoundThisPage>0) { - ((RepositoryJavaClientImpl)repoClient).saveDocListWithoutHandlerProcessing(ctx, repoSession, docList, true); - nRefsFound += nRefsFoundThisPage; - } - pageNumProcessed++; - if(docList.size() 0) { + ((RepositoryJavaClientImpl) repoClient).saveDocListWithoutHandlerProcessing(ctx, repoSession, docList, true); + nRefsFound += nRefsFoundThisPage; + } + + // FIXME: Per REM, set a limit of num objects - something like + // 1000K objects - and also add a log Warning after some threshold + docsScanned += docsInCurrentPage; + if (morePages) { + currentPage++; + } + + } } catch (Exception e) { - logger.error("Internal error updating the AuthorityRefDocs: " + e.getLocalizedMessage()); - logger.debug(Tools.errorToString(e, true)); - throw e; + logger.error("Internal error updating the AuthorityRefDocs: " + e.getLocalizedMessage()); + logger.debug(Tools.errorToString(e, true)); + throw e; } - logger.debug("updateAuthorityRefDocs replaced a total of: "+nRefsFound); + logger.debug("updateAuthorityRefDocs replaced a total of " + nRefsFound + " authority references, within as many as " + docsScanned + " scanned document(s)"); return nRefsFound; } - + private static DocumentModelList findAuthorityRefDocs( - ServiceContext ctx, + ServiceContext ctx, RepositoryClient repoClient, - RepositoryInstance repoSession, - List serviceTypes, + RepositoryInstance repoSession, List serviceTypes, String refName, String refPropName, Map queriedServiceBindings, Map> authRefFieldsByService, String whereClauseAdditions, - int pageSize, int pageNum, boolean computeTotal) throws DocumentException, DocumentNotFoundException { + String orderByClause, + int pageSize, + int pageNum, + boolean computeTotal) throws DocumentException, DocumentNotFoundException { // Get the service bindings for this tenant TenantBindingConfigReaderImpl tReader = @@ -353,58 +384,57 @@ public class RefNameServiceUtils { // We need to get all the procedures, authorities, and objects. List servicebindings = tReader.getServiceBindingsByType(ctx.getTenantId(), serviceTypes); if (servicebindings == null || servicebindings.isEmpty()) { - logger.error("RefNameServiceUtils.getAuthorityRefDocs: No services bindings found, cannot proceed!"); + logger.error("RefNameServiceUtils.getAuthorityRefDocs: No services bindings found, cannot proceed!"); return null; } // Filter the list for current user rights servicebindings = SecurityUtils.getReadableServiceBindingsForCurrentUser(servicebindings); - + ArrayList docTypes = new ArrayList(); - - String query = computeWhereClauseForAuthorityRefDocs(refName, refPropName, docTypes, servicebindings, - queriedServiceBindings, authRefFieldsByService ); + + String query = computeWhereClauseForAuthorityRefDocs(refName, refPropName, docTypes, servicebindings, + queriedServiceBindings, authRefFieldsByService); if (query == null) { // found no authRef fields - nothing to query return null; } // Additional qualifications, like workflow state - if(whereClauseAdditions!=null) { - query += " AND " + whereClauseAdditions; - } + if (Tools.notBlank(whereClauseAdditions)) { + query += " AND " + whereClauseAdditions; + } // Now we have to issue the search - RepositoryJavaClientImpl nuxeoRepoClient = (RepositoryJavaClientImpl)repoClient; + RepositoryJavaClientImpl nuxeoRepoClient = (RepositoryJavaClientImpl) repoClient; DocumentWrapper docListWrapper = nuxeoRepoClient.findDocs(ctx, repoSession, docTypes, query, pageSize, pageNum, computeTotal); // Now we gather the info for each document into the list and return DocumentModelList docList = docListWrapper.getWrappedObject(); return docList; } - private static final boolean READY_FOR_COMPLEX_QUERY = true; - + private static String computeWhereClauseForAuthorityRefDocs( - String refName, - String refPropName, - ArrayList docTypes, - List servicebindings, - Map queriedServiceBindings, - Map> authRefFieldsByService ) { + String refName, + String refPropName, + ArrayList docTypes, + List servicebindings, + Map queriedServiceBindings, + Map> authRefFieldsByService) { boolean fFirst = true; List authRefFieldPaths; for (ServiceBindingType sb : servicebindings) { - // Gets the property names for each part, qualified with the part label (which - // is also the table name, the way that the repository works). + // Gets the property names for each part, qualified with the part label (which + // is also the table name, the way that the repository works). authRefFieldPaths = ServiceBindingUtils.getAllPartsPropertyValues(sb, - refPropName, ServiceBindingUtils.QUALIFIED_PROP_NAMES); + refPropName, ServiceBindingUtils.QUALIFIED_PROP_NAMES); if (authRefFieldPaths.isEmpty()) { continue; } ArrayList authRefsInfo = new ArrayList(); - for(String spec:authRefFieldPaths) { - AuthRefConfigInfo arci = new AuthRefConfigInfo(spec); - authRefsInfo.add(arci); - } + for (String spec : authRefFieldPaths) { + AuthRefConfigInfo arci = new AuthRefConfigInfo(spec); + authRefsInfo.add(arci); + } String docType = sb.getObject().getName(); queriedServiceBindings.put(docType, sb); @@ -420,37 +450,37 @@ public class RefNameServiceUtils { // Note that this will also match the Item itself, but that will get filtered out when // we compute actual matches. AuthorityTermInfo authTermInfo = RefNameUtils.parseAuthorityTermInfo(refName); - - String keywords = RefNameUtils.URN_PREFIX - + " AND " + (authTermInfo.inAuthority.name!=null? - authTermInfo.inAuthority.name:authTermInfo.inAuthority.csid) - + " AND " + (authTermInfo.name!=null? - authTermInfo.name:authTermInfo.csid); - + + String keywords = RefNameUtils.URN_PREFIX + + " AND " + (authTermInfo.inAuthority.name != null + ? authTermInfo.inAuthority.name : authTermInfo.inAuthority.csid) + + " AND " + (authTermInfo.name != null + ? authTermInfo.name : authTermInfo.csid); + String whereClauseStr = QueryManager.createWhereClauseFromKeywords(keywords); - + if (logger.isTraceEnabled()) { - logger.trace("The 'where' clause to find refObjs is: ", whereClauseStr); + logger.trace("The 'where' clause to find refObjs is: ", whereClauseStr); } - - return whereClauseStr; + + return whereClauseStr; } - + /* - * Runs through the list of found docs, processing them. - * If list is non-null, then processing means gather the info for items. - * If list is null, and newRefName is non-null, then processing means replacing and updating. - * If processing/updating, this must be called in teh context of an open session, and caller - * must release Session after calling this. - * + * Runs through the list of found docs, processing them. If list is + * non-null, then processing means gather the info for items. If list is + * null, and newRefName is non-null, then processing means replacing and + * updating. If processing/updating, this must be called in teh context of + * an open session, and caller must release Session after calling this. + * */ private static int processRefObjsDocList( - DocumentModelList docList, - String refName, - Map queriedServiceBindings, - Map> authRefFieldsByService, - List list, - String newAuthorityRefName) { + DocumentModelList docList, + String refName, + Map queriedServiceBindings, + Map> authRefFieldsByService, + List list, + String newAuthorityRefName) { Iterator iter = docList.iterator(); int nRefsFoundTotal = 0; while (iter.hasNext()) { @@ -465,25 +495,25 @@ public class RefNameServiceUtils { "getAuthorityRefDocs: No Service Binding for docType: " + docType); } String serviceContextPath = "/" + sb.getName().toLowerCase() + "/"; - - if(list == null) { // no list - should be update refName case. - if(newAuthorityRefName==null) { - throw new InternalError("processRefObjsDocList() called with neither an itemList nor a new RefName!"); - } - ilistItem = null; - } else { // Have a list - refObjs case - if(newAuthorityRefName!=null) { - throw new InternalError("processRefObjsDocList() called with both an itemList and a new RefName!"); - } - ilistItem = new AuthorityRefDocList.AuthorityRefDocItem(); + + if (list == null) { // no list - should be update refName case. + if (newAuthorityRefName == null) { + throw new InternalError("processRefObjsDocList() called with neither an itemList nor a new RefName!"); + } + ilistItem = null; + } else { // Have a list - refObjs case + if (newAuthorityRefName != null) { + throw new InternalError("processRefObjsDocList() called with both an itemList and a new RefName!"); + } + ilistItem = new AuthorityRefDocList.AuthorityRefDocItem(); String csid = NuxeoUtils.getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString()); ilistItem.setDocId(csid); ilistItem.setUri(serviceContextPath + csid); try { ilistItem.setWorkflowState(docModel.getCurrentLifeCycleState()); - ilistItem.setUpdatedAt(DocHandlerBase.getUpdatedAtAsString(docModel)); - } catch(Exception e) { - logger.error("Error getting core values for doc ["+csid+"]: "+e.getLocalizedMessage()); + ilistItem.setUpdatedAt(DocHandlerBase.getUpdatedAtAsString(docModel)); + } catch (Exception e) { + logger.error("Error getting core values for doc [" + csid + "]: " + e.getLocalizedMessage()); } // The id and URI are the same on all doctypes ilistItem.setDocType(docType); @@ -503,25 +533,24 @@ public class RefNameServiceUtils { //String authRefDescendantField = ""; //String sourceField = ""; int nRefsFoundInDoc = 0; - - ArrayList foundProps - = new ArrayList(); + + ArrayList foundProps = new ArrayList(); try { - findAuthRefPropertiesInDoc(docModel, matchingAuthRefFields, refName, foundProps); - for(RefNameServiceUtils.AuthRefInfo ari:foundProps) { - if(ilistItem != null) { - if(nRefsFoundInDoc == 0) { // First one? - ilistItem.setSourceField(ari.getQualifiedDisplayName()); - } else { // duplicates from one object - ilistItem = cloneAuthRefDocItem(ilistItem, ari.getQualifiedDisplayName()); - } - list.add(ilistItem); - } else { // update refName case - Property propToUpdate = ari.getProperty(); - propToUpdate.setValue(newAuthorityRefName); - } - nRefsFoundInDoc++; - } + findAuthRefPropertiesInDoc(docModel, matchingAuthRefFields, refName, foundProps); + for (RefNameServiceUtils.AuthRefInfo ari : foundProps) { + if (ilistItem != null) { + if (nRefsFoundInDoc == 0) { // First one? + ilistItem.setSourceField(ari.getQualifiedDisplayName()); + } else { // duplicates from one object + ilistItem = cloneAuthRefDocItem(ilistItem, ari.getQualifiedDisplayName()); + } + list.add(ilistItem); + } else { // update refName case + Property propToUpdate = ari.getProperty(); + propToUpdate.setValue(newAuthorityRefName); + } + nRefsFoundInDoc++; + } } catch (ClientException ce) { throw new RuntimeException( "getAuthorityRefDocs: Problem fetching values from repo: " + ce.getLocalizedMessage()); @@ -537,178 +566,155 @@ public class RefNameServiceUtils { } return nRefsFoundTotal; } - + private static AuthorityRefDocList.AuthorityRefDocItem cloneAuthRefDocItem( - AuthorityRefDocList.AuthorityRefDocItem ilistItem, String sourceField) { - AuthorityRefDocList.AuthorityRefDocItem newlistItem = new AuthorityRefDocList.AuthorityRefDocItem(); - newlistItem.setDocId(ilistItem.getDocId()); - newlistItem.setDocName(ilistItem.getDocName()); - newlistItem.setDocNumber(ilistItem.getDocNumber()); - newlistItem.setDocType(ilistItem.getDocType()); - newlistItem.setUri(ilistItem.getUri()); - newlistItem.setSourceField(sourceField); - return newlistItem; + AuthorityRefDocList.AuthorityRefDocItem ilistItem, String sourceField) { + AuthorityRefDocList.AuthorityRefDocItem newlistItem = new AuthorityRefDocList.AuthorityRefDocItem(); + newlistItem.setDocId(ilistItem.getDocId()); + newlistItem.setDocName(ilistItem.getDocName()); + newlistItem.setDocNumber(ilistItem.getDocNumber()); + newlistItem.setDocType(ilistItem.getDocType()); + newlistItem.setUri(ilistItem.getUri()); + newlistItem.setSourceField(sourceField); + return newlistItem; } - - public static List findAuthRefPropertiesInDoc( - DocumentModel docModel, - List authRefFieldInfo, - String refNameToMatch, - List foundProps - ) { - // Assume that authRefFieldInfo is keyed by the field name (possibly mapped for UI) - // and the values are elPaths to the field, where intervening group structures in - // lists of complex structures are replaced with "*". Thus, valid paths include - // the following (note that the ServiceBindingUtils prepend schema names to configured values): - // "schemaname:fieldname" - // "schemaname:scalarlistname" - // "schemaname:complexfieldname/fieldname" - // "schemaname:complexlistname/*/fieldname" - // "schemaname:complexlistname/*/scalarlistname" - // "schemaname:complexlistname/*/complexfieldname/fieldname" - // "schemaname:complexlistname/*/complexlistname/*/fieldname" - // etc. + + public static List findAuthRefPropertiesInDoc( + DocumentModel docModel, + List authRefFieldInfo, + String refNameToMatch, + List foundProps) { + // Assume that authRefFieldInfo is keyed by the field name (possibly mapped for UI) + // and the values are elPaths to the field, where intervening group structures in + // lists of complex structures are replaced with "*". Thus, valid paths include + // the following (note that the ServiceBindingUtils prepend schema names to configured values): + // "schemaname:fieldname" + // "schemaname:scalarlistname" + // "schemaname:complexfieldname/fieldname" + // "schemaname:complexlistname/*/fieldname" + // "schemaname:complexlistname/*/scalarlistname" + // "schemaname:complexlistname/*/complexfieldname/fieldname" + // "schemaname:complexlistname/*/complexlistname/*/fieldname" + // etc. for (AuthRefConfigInfo arci : authRefFieldInfo) { try { - // Get first property and work down as needed. - Property prop = docModel.getProperty(arci.pathEls[0]); - findAuthRefPropertiesInProperty(foundProps, prop, arci, 0, refNameToMatch); - } catch(Exception e) { - logger.error("Problem fetching property: "+arci.pathEls[0]); + // Get first property and work down as needed. + Property prop = docModel.getProperty(arci.pathEls[0]); + findAuthRefPropertiesInProperty(foundProps, prop, arci, 0, refNameToMatch); + } catch (Exception e) { + logger.error("Problem fetching property: " + arci.pathEls[0]); } } return foundProps; } public static List findAuthRefPropertiesInProperty( - List foundProps, - Property prop, - AuthRefConfigInfo arci, - int pathStartIndex, // Supports recursion and we work down the path - String refNameToMatch - ) { - if (pathStartIndex >= arci.pathEls.length) { - throw new ArrayIndexOutOfBoundsException("Index = "+pathStartIndex+" for path: " - +arci.pathEls.toString()); - } - AuthRefInfo ari = null; - if (prop == null) { - return foundProps; - } - - if (prop instanceof StringProperty) { // scalar string - addARIifMatches(refNameToMatch, arci, prop, foundProps); - } else if(prop instanceof List) { - List propList = (List)prop; - // run through list. Must either be list of Strings, or Complex - for (Property listItemProp : propList) { - if(listItemProp instanceof StringProperty) { - if(arci.pathEls.length-pathStartIndex != 1) { - logger.error("Configuration for authRefs does not match schema structure: " - +arci.pathEls.toString()); - break; - } else { - addARIifMatches(refNameToMatch, arci, listItemProp, foundProps); - } - } else if(listItemProp.isComplex()) { - // Just recurse to handle this. Note that since this is a list of complex, - // which should look like listName/*/... we add 2 to the path start index - findAuthRefPropertiesInProperty(foundProps, listItemProp, arci, - pathStartIndex+2, refNameToMatch); - } else { - logger.error("Configuration for authRefs does not match schema structure: " - +arci.pathEls.toString()); - break; - } - } - } else if(prop.isComplex()) { - String localPropName = arci.pathEls[pathStartIndex]; - try { - Property localProp = prop.get(localPropName); - // Now just recurse, pushing down the path 1 step - findAuthRefPropertiesInProperty(foundProps, localProp, arci, - pathStartIndex, refNameToMatch); - } catch(PropertyNotFoundException pnfe) { - logger.error("Could not find property: ["+localPropName+"] in path: "+ - arci.getFullPath()); - // Fall through - ari will be null and we will continue... - } - } else { - logger.error("Configuration for authRefs does not match schema structure: " - +arci.pathEls.toString()); - } - - if (ari != null) { - foundProps.add(ari); //FIXME: REM - This is dead code. 'ari' is never touched after being initalized to null. Why? - } - - return foundProps; + List foundProps, + Property prop, + AuthRefConfigInfo arci, + int pathStartIndex, // Supports recursion and we work down the path + String refNameToMatch) { + if (pathStartIndex >= arci.pathEls.length) { + throw new ArrayIndexOutOfBoundsException("Index = " + pathStartIndex + " for path: " + + arci.pathEls.toString()); + } + AuthRefInfo ari = null; + if (prop == null) { + return foundProps; + } + + if (prop instanceof StringProperty) { // scalar string + addARIifMatches(refNameToMatch, arci, prop, foundProps); + } else if (prop instanceof List) { + List propList = (List) prop; + // run through list. Must either be list of Strings, or Complex + for (Property listItemProp : propList) { + if (listItemProp instanceof StringProperty) { + if (arci.pathEls.length - pathStartIndex != 1) { + logger.error("Configuration for authRefs does not match schema structure: " + + arci.pathEls.toString()); + break; + } else { + addARIifMatches(refNameToMatch, arci, listItemProp, foundProps); + } + } else if (listItemProp.isComplex()) { + // Just recurse to handle this. Note that since this is a list of complex, + // which should look like listName/*/... we add 2 to the path start index + findAuthRefPropertiesInProperty(foundProps, listItemProp, arci, + pathStartIndex + 2, refNameToMatch); + } else { + logger.error("Configuration for authRefs does not match schema structure: " + + arci.pathEls.toString()); + break; + } + } + } else if (prop.isComplex()) { + String localPropName = arci.pathEls[pathStartIndex]; + try { + Property localProp = prop.get(localPropName); + // Now just recurse, pushing down the path 1 step + findAuthRefPropertiesInProperty(foundProps, localProp, arci, + pathStartIndex, refNameToMatch); + } catch (PropertyNotFoundException pnfe) { + logger.error("Could not find property: [" + localPropName + "] in path: " + + arci.getFullPath()); + // Fall through - ari will be null and we will continue... + } + } else { + logger.error("Configuration for authRefs does not match schema structure: " + + arci.pathEls.toString()); + } + + if (ari != null) { + foundProps.add(ari); //FIXME: REM - This is dead code. 'ari' is never touched after being initalized to null. Why? + } + + return foundProps; } - + private static void addARIifMatches( - String refNameToMatch, - AuthRefConfigInfo arci, - Property prop, - List foundProps) { - // Need to either match a passed refName - // OR have no refName to match but be non-empty - try { - String value = (String)prop.getValue(); - if(((refNameToMatch!=null) && refNameToMatch.equals(value)) - || ((refNameToMatch==null) && Tools.notBlank(value))) { - // Found a match - logger.debug("Found a match on property: "+prop.getPath()+" with value: ["+value+"]"); - AuthRefInfo ari = new AuthRefInfo(arci, prop); - foundProps.add(ari); - } - } catch(PropertyException pe) { - logger.debug("PropertyException on: "+prop.getPath()+pe.getLocalizedMessage()); - } + String refNameToMatch, + AuthRefConfigInfo arci, + Property prop, + List foundProps) { + // Need to either match a passed refName + // OR have no refName to match but be non-empty + try { + String value = (String) prop.getValue(); + if (((refNameToMatch != null) && refNameToMatch.equals(value)) + || ((refNameToMatch == null) && Tools.notBlank(value))) { + // Found a match + logger.debug("Found a match on property: " + prop.getPath() + " with value: [" + value + "]"); + AuthRefInfo ari = new AuthRefInfo(arci, prop); + foundProps.add(ari); + } + } catch (PropertyException pe) { + logger.debug("PropertyException on: " + prop.getPath() + pe.getLocalizedMessage()); + } } /* - * Identifies whether the refName was found in the supplied field. - * If passed a new RefName, will set that into fields in which the old one was found. + * Identifies whether the refName was found in the supplied field. If passed + * a new RefName, will set that into fields in which the old one was found. * - * Only works for: - * * Scalar fields - * * Repeatable scalar fields (aka multi-valued fields) + * Only works for: * Scalar fields * Repeatable scalar fields (aka + * multi-valued fields) * - * Does not work for: - * * Structured fields (complexTypes) - * * Repeatable structured fields (repeatable complexTypes) - private static int refNameFoundInField(String oldRefName, Property fieldValue, String newRefName) { - int nFound = 0; - if (fieldValue instanceof List) { - List fieldValueList = (List) fieldValue; - for (Property listItemValue : fieldValueList) { - try { - if ((listItemValue instanceof StringProperty) - && oldRefName.equalsIgnoreCase((String)listItemValue.getValue())) { - nFound++; - if(newRefName!=null) { - fieldValue.setValue(newRefName); - } else { - // We cannot quit after the first, if we are replacing values. - // If we are just looking (not replacing), finding one is enough. - break; - } - } - } catch( PropertyException pe ) {} - } - } else { - try { - if ((fieldValue instanceof StringProperty) - && oldRefName.equalsIgnoreCase((String)fieldValue.getValue())) { - nFound++; - if(newRefName!=null) { - fieldValue.setValue(newRefName); - } - } - } catch( PropertyException pe ) {} - } - return nFound; - } + * Does not work for: * Structured fields (complexTypes) * Repeatable + * structured fields (repeatable complexTypes) private static int + * refNameFoundInField(String oldRefName, Property fieldValue, String + * newRefName) { int nFound = 0; if (fieldValue instanceof List) { + * List fieldValueList = (List) fieldValue; for (Property + * listItemValue : fieldValueList) { try { if ((listItemValue instanceof + * StringProperty) && + * oldRefName.equalsIgnoreCase((String)listItemValue.getValue())) { + * nFound++; if(newRefName!=null) { fieldValue.setValue(newRefName); } else + * { // We cannot quit after the first, if we are replacing values. // If we + * are just looking (not replacing), finding one is enough. break; } } } + * catch( PropertyException pe ) {} } } else { try { if ((fieldValue + * instanceof StringProperty) && + * oldRefName.equalsIgnoreCase((String)fieldValue.getValue())) { nFound++; + * if(newRefName!=null) { fieldValue.setValue(newRefName); } } } catch( + * PropertyException pe ) {} } return nFound; } */ } - -- 2.47.3