List of usage examples for java.text DateFormat getDateTimeInstance
public static final DateFormat getDateTimeInstance()
From source file:org.archive.crawler.extractor.ExtractorHTML.java
public void extract(CrawlURI curi) { if (!isHttpTransactionContentToProcess(curi) || !(isExpectedMimeType(curi.getContentType(), "text/html") || isExpectedMimeType(curi.getContentType(), "application/xhtml") || isExpectedMimeType(curi.getContentType(), "text/vnd.wap.wml") || isExpectedMimeType(curi.getContentType(), "application/vnd.wap.wml") || isExpectedMimeType(curi.getContentType(), "application/vnd.wap.xhtml"))) { return;//from w ww.ja va2s . co m } final boolean ignoreUnexpectedHTML = ((Boolean) getUncheckedAttribute(curi, ATTR_IGNORE_UNEXPECTED_HTML)) .booleanValue(); if (ignoreUnexpectedHTML) { try { if (!isHtmlExpectedHere(curi)) { // HTML was not expected (eg a GIF was expected) so ignore // (as if a soft 404) return; } } catch (URIException e) { logger.severe("Failed expectedHTML test: " + e.getMessage()); } } this.numberOfCURIsHandled++; ReplayCharSequence cs = null; String codecharset = "utf-8"; try { HttpRecorder hr = curi.getHttpRecorder(); if (hr == null) { throw new IOException("Why is recorder null here?"); } cs = hr.getReplayCharSequence(); // codecharset = hr.getCharacterEncoding(); /* * { writer_c = new BufferedWriter(new FileWriter( new * File("D:\\code.txt"), true)); writer_c.write(curi.toString() + * ": " + codecharset + "\r\n"); writer_c.close(); } */ } catch (IOException e) { curi.addLocalizedError(this.getName(), e, "Failed get of replay char sequence " + curi.toString() + " " + e.getMessage()); logger.log(Level.SEVERE, "Failed get of replay char sequence in " + Thread.currentThread().getName(), e); } if (cs == null) { return; } // We have a ReplayCharSequence open. Wrap all in finally so we // for sure close it before we leave. try { // Extract all links from the charsequence extract(curi, cs); // { System.out.println(curi.toString() + " Processing"); try { String uri = curi.toString(); String temurl = uri.substring(7); temurl = temurl.replaceAll("[\\?/:*|<>\"]", "_"); temurl = temurl.replaceAll("#|%|@|&|!|~|'", "11"); if (temurl.length() > 30) temurl = temurl.substring(0, 30); xmlReader xmlreader = new xmlReader(); //File filenameo = new File("D:/Work/WEB app/SearchEngineServer/crawler/dowloaded_files/" + DateFormat.getDateInstance().format(new Date())); File filenameo = new File(xmlreader.getCrawlerPath("download")); filenameo.mkdirs(); String file_path = filenameo.getAbsolutePath() + "/" + temurl + ".html"; File filename = new File(file_path); if (!filename.exists()) { filename.createNewFile(); System.out.println("Created:" + " " + curi.toString() + ".html"); OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(filename), codecharset); BufferedWriter writer = new BufferedWriter(write); writer.write(uri + "\r\n"); writer.write(DateFormat.getDateTimeInstance().format(new Date()) + "\r\n"); writer.write(codecharset + "\r\n"); writer.write("<begin!>\r\n"); String content = cs.toString(); writer.write(content); writer.close(); } } catch (Exception e) { } } // Set flag to indicate that link extraction is completed. curi.linkExtractorFinished(); } finally { if (cs != null) { try { cs.close(); } catch (IOException ioe) { logger.warning(TextUtils.exceptionToString("Failed close of ReplayCharSequence.", ioe)); } } } }
From source file:org.apache.wiki.auth.user.XMLUserDatabase.java
/** * After loading the DOM, this method sanity-checks the dates in the DOM and makes * sure they are formatted properly. This is sort-of hacky, but it should work. *///from w w w.ja v a 2 s. c om private void sanitizeDOM() { if (c_dom == null) { throw new IllegalStateException("FATAL: database does not exist"); } NodeList users = c_dom.getElementsByTagName(USER_TAG); for (int i = 0; i < users.getLength(); i++) { Element user = (Element) users.item(i); // Sanitize UID (and generate a new one if one does not exist) String uid = user.getAttribute(UID).trim(); if (uid == null || uid.length() == 0 || "-1".equals(uid)) { uid = String.valueOf(generateUid(this)); user.setAttribute(UID, uid); } // Sanitize dates String loginName = user.getAttribute(LOGIN_NAME); String created = user.getAttribute(CREATED); String modified = user.getAttribute(LAST_MODIFIED); DateFormat c_format = new SimpleDateFormat(DATE_FORMAT); try { created = c_format.format(c_format.parse(created)); modified = c_format.format(c_format.parse(modified)); user.setAttribute(CREATED, created); user.setAttribute(LAST_MODIFIED, modified); } catch (ParseException e) { try { created = c_format.format(DateFormat.getDateTimeInstance().parse(created)); modified = c_format.format(DateFormat.getDateTimeInstance().parse(modified)); user.setAttribute(CREATED, created); user.setAttribute(LAST_MODIFIED, modified); } catch (ParseException e2) { log.warn("Could not parse 'created' or 'lastModified' attribute for profile '" + loginName + "'." + " It may have been tampered with."); } } } }
From source file:edu.harvard.i2b2.eclipse.LoginView.java
/** * get current date as string used for logi * /*from ww w . j a v a 2s . c om*/ * @return */ public static String getNow() { return DateFormat.getDateTimeInstance().format(new Date()); }
From source file:org.pengyou.ooo.PublishAsDialog.java
private String formatList(String[] t) { String res = new String(); if (t[2] == "COLLECTION") { if (t[4].length() > 21) res = t[4].substring(0, 20) + ""; else//from w ww .j ava 2 s . c om res = t[4]; //res = " " + res; res = " " + res; } else { if (t[4].length() > 23) res = t[4].substring(0, 22) + ""; else res = t[4]; } //int l = res.length(); while (res.length() < 25) res += " "; res += t[6]; while (res.length() < 42) res += " "; Locale locale = Locale.FRENCH; Date date = null; String s = null; try { date = DateFormat.getDateTimeInstance().parse(t[5]); s = DateFormat.getDateInstance(DateFormat.MEDIUM, locale).format(date); res += s; while (res.length() < 57) res += " "; } catch (ParseException e) { e.printStackTrace(); log.log(Level.DEBUG, e.getLocalizedMessage()); } date = null; s = null; try { date = DateFormat.getDateTimeInstance().parse(t[3]); s = DateFormat.getDateInstance(DateFormat.MEDIUM, locale).format(date); res += s; while (res.length() < 71) res += " "; } catch (ParseException e) { e.printStackTrace(); log.log(Level.DEBUG, e.getLocalizedMessage()); } return res; }
From source file:de.knowwe.defi.usermanager.XMLUserDatabase.java
/** * After loading the DOM, this method sanity-checks the dates in the DOM and makes * sure they are formatted properly. This is sort-of hacky, but it should work. *///ww w.j a va 2s . co m private void sanitizeDOM() { if (c_dom == null) { throw new IllegalStateException("FATAL: database does not exist"); } NodeList users = c_dom.getElementsByTagName(USER_TAG); for (int i = 0; i < users.getLength(); i++) { Element user = (Element) users.item(i); // Sanitize UID (and generate a new one if one does not exist) String uid = user.getAttribute(UID).trim(); if (uid == null || uid.isEmpty() || "-1".equals(uid)) { uid = String.valueOf(generateUid(this)); user.setAttribute(UID, uid); } // Sanitize dates String loginName = user.getAttribute(LOGIN_NAME); String created = user.getAttribute(CREATED); String modified = user.getAttribute(LAST_MODIFIED); DateFormat c_format = new SimpleDateFormat(DATE_FORMAT); try { created = c_format.format(c_format.parse(created)); modified = c_format.format(c_format.parse(modified)); user.setAttribute(CREATED, created); user.setAttribute(LAST_MODIFIED, modified); } catch (ParseException e) { try { created = c_format.format(DateFormat.getDateTimeInstance().parse(created)); modified = c_format.format(DateFormat.getDateTimeInstance().parse(modified)); user.setAttribute(CREATED, created); user.setAttribute(LAST_MODIFIED, modified); } catch (ParseException e2) { Log.warning("Could not parse 'created' or 'lastModified' attribute for profile '" + loginName + "'." + " It may have been tampered with."); } } } }
From source file:com.irccloud.android.activity.MainActivity.java
private void show_topic_popup() { if (buffer == null) return;//from ww w . j a v a2 s.c om ChannelsDataSource.Channel c = ChannelsDataSource.getInstance().getChannelForBuffer(buffer.bid); if (c != null) { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setInverseBackgroundForced(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB); View v = getLayoutInflater().inflate(R.layout.dialog_topic, null); if (c.topic_text.length() > 0) { String author = ""; if (c.topic_author != null && c.topic_author.length() > 0) { author = " Set by " + c.topic_author; if (c.topic_time > 0) { author += " on " + DateFormat.getDateTimeInstance().format(new Date(c.topic_time * 1000)); } v.findViewById(R.id.setBy).setVisibility(View.VISIBLE); ((TextView) v.findViewById(R.id.setBy)).setText(author); } ((TextView) v.findViewById(R.id.topic)).setText(ColorFormatter.html_to_spanned( ColorFormatter.emojify(ColorFormatter.irc_to_html(TextUtils.htmlEncode(c.topic_text))), true, server)); } else { ((TextView) v.findViewById(R.id.topic)).setText("No topic set."); } if (c.mode.length() > 0) { v.findViewById(R.id.mode).setVisibility(View.VISIBLE); ((TextView) v.findViewById(R.id.mode)).setText("Mode: +" + c.mode); for (ChannelsDataSource.Mode m : c.modes) { switch (m.mode) { case "i": v.findViewById(R.id.mode_i).setVisibility(View.VISIBLE); break; case "k": v.findViewById(R.id.mode_k).setVisibility(View.VISIBLE); ((TextView) v.findViewById(R.id.key)).setText(m.param); break; case "m": v.findViewById(R.id.mode_m).setVisibility(View.VISIBLE); break; case "n": v.findViewById(R.id.mode_n).setVisibility(View.VISIBLE); break; case "p": v.findViewById(R.id.mode_p).setVisibility(View.VISIBLE); break; case "s": v.findViewById(R.id.mode_s).setVisibility(View.VISIBLE); break; case "t": v.findViewById(R.id.mode_t).setVisibility(View.VISIBLE); break; } } } builder.setView(v); builder.setNegativeButton("Close", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); boolean canEditTopic; if (c.hasMode("t")) { UsersDataSource.User self_user = UsersDataSource.getInstance().getUser(buffer.bid, server.nick); canEditTopic = (self_user != null && (self_user.mode.contains(server != null ? server.MODE_OPER : "Y") || self_user.mode.contains(server != null ? server.MODE_OWNER : "q") || self_user.mode.contains(server != null ? server.MODE_ADMIN : "a") || self_user.mode.contains(server != null ? server.MODE_OP : "o") || self_user.mode.contains(server != null ? server.MODE_HALFOP : "h"))); } else { canEditTopic = true; } if (canEditTopic) { builder.setPositiveButton("Edit Topic", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); editTopic(); } }); } final AlertDialog dialog = builder.create(); dialog.setOwnerActivity(MainActivity.this); dialog.show(); ((TextView) v.findViewById(R.id.topic)).setMovementMethod(new LinkMovementMethod() { @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { if (super.onTouchEvent(widget, buffer, event) && event.getAction() == MotionEvent.ACTION_UP) { dialog.dismiss(); return true; } return false; } }); } }
From source file:com.javielinux.utils.Utils.java
public static String timeFromTweetExtended(Context cnt, Date timeTweet) { if (Integer.parseInt(Utils.getPreference(cnt).getString("prf_date_format", "1")) == 1) { if (timeTweet != null) { Date now = new Date(); long diff = ((now.getTime() - timeTweet.getTime())) / 1000; String out = ""; if (diff < 60) { out = String.valueOf(diff) + " " + cnt.getString(R.string.seconds); } else { // minutos long sec = diff % 60; diff = diff / 60;//from w w w . ja va 2 s .com if (diff < 60) { out = String.valueOf(diff) + " " + cnt.getString(R.string.minutes) + " " + cnt.getString(R.string.and) + " " + sec + " " + cnt.getString(R.string.seconds); } else { // horas long min = diff % 60; diff = diff / 60; if (diff < 24) { out = String.valueOf(diff) + " " + cnt.getString(R.string.hours) + " " + cnt.getString(R.string.and) + " " + min + " " + cnt.getString(R.string.minutes); } else { // dias long hours = diff % 24; diff = diff / 24; out = String.valueOf(diff) + " " + cnt.getString(R.string.days) + " " + cnt.getString(R.string.and) + " " + hours + " " + cnt.getString(R.string.hours); } } } return cnt.getString(R.string.date_long, out); } } else { return DateFormat.getDateTimeInstance().format(timeTweet); } return ""; }
From source file:org.opendatakit.briefcase.util.ExportToCsv.java
private boolean processInstance(File instanceDir) { File submission = new File(instanceDir, "submission.xml"); if (!submission.exists() || !submission.isFile()) { EventBus.publish(new ExportProgressEvent( "Submission not found for instance directory: " + instanceDir.getPath())); return false; }//from www. jav a 2 s.c om EventBus.publish(new ExportProgressEvent("Processing instance: " + instanceDir.getName())); // If we are encrypted, be sure the temporary directory // that will hold the unencrypted files is created and empty. // If we aren't encrypted, the temporary directory // is the same as the instance directory. File unEncryptedDir; if (briefcaseLfd.isFileEncryptedForm()) { // create or clean-up the temp directory that will hold the unencrypted // files. Do this in the outputDir so that the briefcase storage location // can be a read-only network mount. issue 676. unEncryptedDir = new File(outputDir, ".temp"); if (unEncryptedDir.exists()) { // silently delete it... try { FileUtils.deleteDirectory(unEncryptedDir); } catch (IOException e) { e.printStackTrace(); EventBus.publish(new ExportProgressEvent( "Unable to delete stale temp directory: " + unEncryptedDir.getAbsolutePath())); return false; } } if (!unEncryptedDir.mkdirs()) { EventBus.publish(new ExportProgressEvent( "Unable to create temp directory: " + unEncryptedDir.getAbsolutePath())); return false; } } else { unEncryptedDir = instanceDir; } // parse the xml document (this is the manifest if encrypted)... Document doc; boolean isValidated = false; try { doc = XmlManipulationUtils.parseXml(submission); } catch (ParsingException e) { e.printStackTrace(); EventBus.publish(new ExportProgressEvent( "Error parsing submission " + instanceDir.getName() + " Cause: " + e.toString())); return false; } catch (FileSystemException e) { e.printStackTrace(); EventBus.publish(new ExportProgressEvent( "Error parsing submission " + instanceDir.getName() + " Cause: " + e.toString())); return false; } String submissionDate = null; // extract the submissionDate, if present, from the attributes // of the root element of the submission or submission manifest (if encrypted). submissionDate = doc.getRootElement().getAttributeValue(null, "submissionDate"); if (submissionDate == null || submissionDate.length() == 0) { submissionDate = null; } else { Date theDate = WebUtils.parseDate(submissionDate); DateFormat formatter = DateFormat.getDateTimeInstance(); submissionDate = formatter.format(theDate); // just return true to skip records out of range if (startDate != null && theDate.before(startDate)) { log.info("Submission date is before specified, skipping: " + instanceDir.getName()); return true; } if (endDate != null && theDate.after(endDate)) { log.info("Submission date is after specified, skipping: " + instanceDir.getName()); return true; } // don't export records without dates if either date is set if ((startDate != null || endDate != null) && submissionDate == null) { log.info("No submission date found, skipping: " + instanceDir.getName()); return true; } } // Beyond this point, we need to have a finally block that // will clean up any decrypted files whenever there is any // failure. try { if (briefcaseLfd.isFileEncryptedForm()) { // Decrypt the form and all its media files into the // unEncryptedDir and validate the contents of all // those files. // NOTE: this changes the value of 'doc' try { FileSystemUtils.DecryptOutcome outcome = FileSystemUtils.decryptAndValidateSubmission(doc, briefcaseLfd.getPrivateKey(), instanceDir, unEncryptedDir); doc = outcome.submission; isValidated = outcome.isValidated; } catch (ParsingException e) { e.printStackTrace(); EventBus.publish(new ExportProgressEvent( "Error decrypting submission " + instanceDir.getName() + " Cause: " + e.toString())); return false; } catch (FileSystemException e) { e.printStackTrace(); EventBus.publish(new ExportProgressEvent( "Error decrypting submission " + instanceDir.getName() + " Cause: " + e.toString())); return false; } catch (CryptoException e) { e.printStackTrace(); EventBus.publish(new ExportProgressEvent( "Error decrypting submission " + instanceDir.getName() + " Cause: " + e.toString())); return false; } } String instanceId = null; String base64EncryptedFieldKey = null; // find an instanceId to use... try { FormInstanceMetadata sim = XmlManipulationUtils.getFormInstanceMetadata(doc.getRootElement()); instanceId = sim.instanceId; base64EncryptedFieldKey = sim.base64EncryptedFieldKey; } catch (ParsingException e) { e.printStackTrace(); EventBus.publish(new ExportProgressEvent("Could not extract metadata from submission: " + submission.getAbsolutePath() + " Cause: " + e.toString())); return false; } if (instanceId == null || instanceId.length() == 0) { // if we have no instanceID, and there isn't any in the file, // use the checksum as the id. // NOTE: encrypted submissions always have instanceIDs. // This is for legacy non-OpenRosa forms. long checksum; try { checksum = FileUtils.checksumCRC32(submission); } catch (IOException e1) { e1.printStackTrace(); EventBus.publish(new ExportProgressEvent("Failed during computing of crc: " + e1.getMessage())); return false; } instanceId = "crc32:" + Long.toString(checksum); } if (terminationFuture.isCancelled()) { EventBus.publish(new ExportProgressEvent("ABORTED")); return false; } EncryptionInformation ei = null; if (base64EncryptedFieldKey != null) { try { ei = new EncryptionInformation(base64EncryptedFieldKey, instanceId, briefcaseLfd.getPrivateKey()); } catch (CryptoException e) { e.printStackTrace(); EventBus.publish(new ExportProgressEvent("Error establishing field decryption for submission " + instanceDir.getName() + " Cause: " + e.toString())); return false; } } // emit the csv record... try { OutputStreamWriter osw = fileMap.get(briefcaseLfd.getSubmissionElement()); emitString(osw, true, submissionDate); emitSubmissionCsv(osw, ei, doc.getRootElement(), briefcaseLfd.getSubmissionElement(), briefcaseLfd.getSubmissionElement(), false, instanceId, unEncryptedDir); emitString(osw, false, instanceId); if (briefcaseLfd.isFileEncryptedForm()) { emitString(osw, false, Boolean.toString(isValidated)); if (!isValidated) { EventBus.publish(new ExportProgressEvent("Decrypted submission " + instanceDir.getName() + " may be missing attachments and could not be validated.")); } } osw.append("\n"); return true; } catch (IOException e) { e.printStackTrace(); EventBus.publish(new ExportProgressEvent("Failed writing csv: " + e.getMessage())); return false; } } finally { if (briefcaseLfd.isFileEncryptedForm()) { // destroy the temp directory and its contents... try { FileUtils.deleteDirectory(unEncryptedDir); } catch (IOException e) { e.printStackTrace(); EventBus.publish( new ExportProgressEvent("Unable to remove decrypted files: " + e.getMessage())); return false; } } } }
From source file:org.alfresco.repo.security.sync.TenantChainingUserRegistrySynchronizer.java
/** * Synchronizes local groups and users with a {@link UserRegistry} for a * particular zone, optionally handling deletions. * /*from w w w . ja va 2 s. c o m*/ * @param zone * the zone id. This identifier is used to tag all created groups * and users, so that in the future we can tell those that have * been deleted from the registry. * @param userRegistry * the user registry for the zone. * @param forceUpdate * Should the complete set of users and groups be updated / * created locally or just those known to have changed since the * last sync? When <code>true</code> then <i>all</i> users and * groups are queried from the user registry and updated locally. * When <code>false</code> then each source is only queried for * those users and groups modified since the most recent * modification date of all the objects last queried from that * same source. * @param isFullSync * Should a complete set of user and group IDs be queried from * the user registries in order to determine deletions? This * parameter is independent of <code>force</code> as a separate * query is run to process updates. * @param splitTxns * Can the modifications to Alfresco be split across multiple * transactions for maximum performance? If <code>true</code>, * users and groups are created/updated in batches for increased * performance. If <code>false</code>, all users and groups are * processed in the current transaction. This is required if * calling synchronously (e.g. in response to an authentication * event in the same transaction). * @param visitedZoneIds * the set of zone ids already processed. These zones have * precedence over the current zone when it comes to group name * 'collisions'. If a user or group is queried that already * exists locally but is tagged with one of the zones in this * set, then it will be ignored as this zone has lower priority. * @param allZoneIds * the set of all zone ids in the authentication chain. Helps us * work out whether the zone information recorded against a user * or group is invalid for the current authentication chain and * whether the user or group needs to be 're-zoned'. */ private void syncWithPlugin(final String zone, UserRegistry userRegistry, boolean forceUpdate, boolean isFullSync, boolean splitTxns, final Set<String> visitedZoneIds, final Set<String> allZoneIds) { // Create a prefixed zone ID for use with the authority service final String zoneId = AuthorityService.ZONE_AUTH_EXT_PREFIX + zone; // Ensure that the zoneId exists before multiple threads start using it this.transactionService.getRetryingTransactionHelper() .doInTransaction(new RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { authorityService.getOrCreateZone(zoneId); return null; } }, false, splitTxns); // The set of zones we associate with new objects (default plus registry // specific) final Set<String> zoneSet = getZones(zoneId); long lastModifiedMillis = forceUpdate ? -1 : getMostRecentUpdateTime(TenantChainingUserRegistrySynchronizer.GROUP_LAST_MODIFIED_ATTRIBUTE, zoneId, splitTxns); Date lastModified = lastModifiedMillis == -1 ? null : new Date(lastModifiedMillis); if (TenantChainingUserRegistrySynchronizer.logger.isInfoEnabled()) { if (lastModified == null) { TenantChainingUserRegistrySynchronizer.logger .info("Retrieving all groups from user registry '" + zone + "'"); } else { TenantChainingUserRegistrySynchronizer.logger.info( "Retrieving groups changed since " + DateFormat.getDateTimeInstance().format(lastModified) + " from user registry '" + zone + "'"); } } // First, analyze the group structure. Create maps of authorities to // their parents for associations to create // and delete. Also deal with 'overlaps' with other zones in the // authentication chain. final BatchProcessor<NodeDescription> groupProcessor = new BatchProcessor<NodeDescription>( zone + " Group Analysis", this.transactionService.getRetryingTransactionHelper(), userRegistry.getGroups(lastModified), this.workerThreads, 20, this.applicationEventPublisher, TenantChainingUserRegistrySynchronizer.logger, this.loggingInterval); class Analyzer extends BaseBatchProcessWorker<NodeDescription> { private final Map<String, String> groupsToCreate = new TreeMap<String, String>(); private final Map<String, Set<String>> personParentAssocsToCreate = newPersonMap(); private final Map<String, Set<String>> personParentAssocsToDelete = newPersonMap(); private Map<String, Set<String>> groupParentAssocsToCreate = new TreeMap<String, Set<String>>(); private final Map<String, Set<String>> groupParentAssocsToDelete = new TreeMap<String, Set<String>>(); private final Map<String, Set<String>> finalGroupChildAssocs = new TreeMap<String, Set<String>>(); private List<String> personsProcessed = new LinkedList<String>(); private Set<String> allZonePersons = Collections.emptySet(); private Set<String> deletionCandidates; private long latestTime; public Analyzer(final long latestTime) { this.latestTime = latestTime; } public long getLatestTime() { return this.latestTime; } public Set<String> getDeletionCandidates() { return this.deletionCandidates; } public String getIdentifier(NodeDescription entry) { return entry.getSourceId(); } public void process(final NodeDescription group) throws Throwable { PropertyMap groupProperties = group.getProperties(); String tenantDomain = (String) groupProperties.get(ContentModel.PROP_ORGANIZATION); logger.debug("Process group: " + groupProperties.get(ContentModel.PROP_AUTHORITY_NAME) + (tenantDomain == null ? "" : ("/" + tenantDomain))); if (tenantDomain != null) { if (!isTenantEnabled(tenantDomain)) { return; } AuthenticationUtil.runAs(new RunAsWork<Void>() { @Override public Void doWork() throws Exception { processInTenantMode(group); return null; } }, SEIPTenantIntegration.getSystemUserByTenantId(tenantDomain)); } else { processInTenantMode(group); } } private void processInTenantMode(NodeDescription group) { PropertyMap groupProperties = group.getProperties(); String groupName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_NAME); String groupShortName = TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(groupName); Set<String> groupZones = TenantChainingUserRegistrySynchronizer.this.authorityService .getAuthorityZones(groupName); if (groupZones == null) { // The group did not exist at all updateGroup(group, false); } else { // Check whether the group is in any of the authentication // chain zones Set<String> intersection = new TreeSet<String>(groupZones); intersection.retainAll(allZoneIds); // Check whether the group is in any of the higher priority // authentication chain zones Set<String> visited = new TreeSet<String>(intersection); visited.retainAll(visitedZoneIds); if (groupZones.contains(zoneId)) { // The group already existed in this zone: update the // group updateGroup(group, true); } else if (!visited.isEmpty()) { // A group that exists in a different zone with higher // precedence return; } else if (!allowDeletions || intersection.isEmpty()) { // Deletions are disallowed or the group exists, but not // in a zone that's in the authentication // chain. May be due to upgrade or zone changes. Let's // re-zone them if (TenantChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { TenantChainingUserRegistrySynchronizer.logger.warn("Updating group '" + groupShortName + "'. This group will in future be assumed to originate from user registry '" + zone + "'."); } updateAuthorityZones(groupName, groupZones, zoneSet); // The group now exists in this zone: update the group updateGroup(group, true); } else { // The group existed, but in a zone with lower // precedence if (TenantChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { TenantChainingUserRegistrySynchronizer.logger.warn("Recreating occluded group '" + groupShortName + "'. This group was previously created through synchronization with a lower priority user registry."); } TenantChainingUserRegistrySynchronizer.this.authorityService.deleteAuthority(groupName); // create the group updateGroup(group, false); } } synchronized (this) { // Maintain the last modified date Date groupLastModified = group.getLastModified(); if (groupLastModified != null) { this.latestTime = Math.max(this.latestTime, groupLastModified.getTime()); } } } // Recursively walks and caches the authorities relating to and from // this group so that we can later detect potential cycles private Set<String> getContainedAuthorities(String groupName) { // Return the cached children if it is processed Set<String> children = this.finalGroupChildAssocs.get(groupName); if (children != null) { return children; } // First, recurse to the parent most authorities for (String parent : TenantChainingUserRegistrySynchronizer.this.authorityService .getContainingAuthorities(null, groupName, true)) { getContainedAuthorities(parent); } // Now descend on unprocessed parents. return cacheContainedAuthorities(groupName); } private Set<String> cacheContainedAuthorities(String groupName) { // Return the cached children if it is processed Set<String> children = this.finalGroupChildAssocs.get(groupName); if (children != null) { return children; } // Descend on unprocessed parents. children = TenantChainingUserRegistrySynchronizer.this.authorityService .getContainedAuthorities(null, groupName, true); this.finalGroupChildAssocs.put(groupName, children); for (String child : children) { if (AuthorityType.getAuthorityType(child) != AuthorityType.USER) { cacheContainedAuthorities(child); } } return children; } private synchronized void updateGroup(NodeDescription group, boolean existed) { PropertyMap groupProperties = group.getProperties(); String groupName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_NAME); String groupDisplayName = (String) groupProperties.get(ContentModel.PROP_AUTHORITY_DISPLAY_NAME); if (groupDisplayName == null) { groupDisplayName = TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(groupName); } // Divide the child associations into person and group // associations, dealing with case sensitivity Set<String> newChildPersons = newPersonSet(); Set<String> newChildGroups = new TreeSet<String>(); for (String child : group.getChildAssociations()) { if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) { newChildPersons.add(child); } else { newChildGroups.add(child); } } // Account for differences if already existing if (existed) { // Update the display name now TenantChainingUserRegistrySynchronizer.this.authorityService.setAuthorityDisplayName(groupName, groupDisplayName); // Work out the association differences for (String child : new TreeSet<String>(getContainedAuthorities(groupName))) { if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) { if (!newChildPersons.remove(child)) { recordParentAssociationDeletion(child, groupName); } } else { if (!newChildGroups.remove(child)) { recordParentAssociationDeletion(child, groupName); } } } } // Mark as created if new else { // Make sure each group to be created features in the // association deletion map (as these are handled in the // same phase) recordParentAssociationDeletion(groupName, null); this.groupsToCreate.put(groupName, groupDisplayName); } // Create new associations for (String child : newChildPersons) { // Make sure each person with association changes features // as a key in the deletion map recordParentAssociationDeletion(child, null); recordParentAssociationCreation(child, groupName); } for (String child : newChildGroups) { // Make sure each group with association changes features as // a key in the deletion map recordParentAssociationDeletion(child, null); recordParentAssociationCreation(child, groupName); } } private void recordParentAssociationDeletion(String child, String parent) { Map<String, Set<String>> parentAssocs; if (AuthorityType.getAuthorityType(child) == AuthorityType.USER) { parentAssocs = this.personParentAssocsToDelete; } else { // Reflect the change in the map of final group associations // (for cycle detection later) parentAssocs = this.groupParentAssocsToDelete; if (parent != null) { Set<String> children = this.finalGroupChildAssocs.get(parent); children.remove(child); } } Set<String> parents = parentAssocs.get(child); if (parents == null) { parents = new TreeSet<String>(); parentAssocs.put(child, parents); } if (parent != null) { parents.add(parent); } } private void recordParentAssociationCreation(String child, String parent) { Map<String, Set<String>> parentAssocs = AuthorityType.getAuthorityType(child) == AuthorityType.USER ? this.personParentAssocsToCreate : this.groupParentAssocsToCreate; Set<String> parents = parentAssocs.get(child); if (parents == null) { parents = new TreeSet<String>(); parentAssocs.put(child, parents); } if (parent != null) { parents.add(parent); } } private void validateGroupParentAssocsToCreate() { Iterator<Map.Entry<String, Set<String>>> i = this.groupParentAssocsToCreate.entrySet().iterator(); while (i.hasNext()) { Map.Entry<String, Set<String>> entry = i.next(); String group = entry.getKey(); Set<String> parents = entry.getValue(); Deque<String> visited = new LinkedList<String>(); Iterator<String> j = parents.iterator(); while (j.hasNext()) { String parent = j.next(); visited.add(parent); if (validateAuthorityChildren(visited, group)) { // The association validated - commit it Set<String> children = finalGroupChildAssocs.get(parent); if (children == null) { children = new TreeSet<String>(); finalGroupChildAssocs.put(parent, children); } children.add(group); } else { // The association did not validate - prune it out if (logger.isWarnEnabled()) { TenantChainingUserRegistrySynchronizer.logger.warn("Not adding group '" + TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(group) + "' to group '" + TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(parent) + "' as this creates a cyclic relationship"); } j.remove(); } visited.removeLast(); } if (parents.isEmpty()) { i.remove(); } } // Sort the group associations in parent-first order (root // groups first) to minimize reindexing overhead Map<String, Set<String>> sortedGroupAssociations = new LinkedHashMap<String, Set<String>>( this.groupParentAssocsToCreate.size() * 2); Deque<String> visited = new LinkedList<String>(); for (String authority : this.groupParentAssocsToCreate.keySet()) { visitGroupParentAssocs(visited, authority, this.groupParentAssocsToCreate, sortedGroupAssociations); } this.groupParentAssocsToCreate = sortedGroupAssociations; } private boolean validateAuthorityChildren(Deque<String> visited, String authority) { if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER) { return true; } if (visited.contains(authority)) { return false; } visited.add(authority); try { Set<String> children = this.finalGroupChildAssocs.get(authority); if (children != null) { for (String child : children) { if (!validateAuthorityChildren(visited, child)) { return false; } } } return true; } finally { visited.removeLast(); } } /** * Visits the given authority by recursively visiting its parents in * associationsOld and then adding the authority to associationsNew. * Used to sort associationsOld into 'parent-first' order to * minimize reindexing overhead. * * @param visited * The ancestors that form the path to the authority to * visit. Allows detection of cyclic child associations. * @param authority * the authority to visit * @param associationsOld * the association map to sort * @param associationsNew * the association map to add to in parent-first order */ private boolean visitGroupParentAssocs(Deque<String> visited, String authority, Map<String, Set<String>> associationsOld, Map<String, Set<String>> associationsNew) { if (visited.contains(authority)) { // Prevent cyclic paths (Shouldn't happen as we've already // validated) return false; } visited.add(authority); try { if (!associationsNew.containsKey(authority)) { Set<String> oldParents = associationsOld.get(authority); if (oldParents != null) { Set<String> newParents = new TreeSet<String>(); for (String parent : oldParents) { if (visitGroupParentAssocs(visited, parent, associationsOld, associationsNew)) { newParents.add(parent); } } associationsNew.put(authority, newParents); } } return true; } finally { visited.removeLast(); } } private Set<String> newPersonSet() { return TenantChainingUserRegistrySynchronizer.this.personService.getUserNamesAreCaseSensitive() ? new TreeSet<String>() : new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); } private Map<String, Set<String>> newPersonMap() { return TenantChainingUserRegistrySynchronizer.this.personService.getUserNamesAreCaseSensitive() ? new TreeMap<String, Set<String>>() : new TreeMap<String, Set<String>>(String.CASE_INSENSITIVE_ORDER); } private void logRetainParentAssociations(Map<String, Set<String>> parentAssocs, Set<String> toRetain) { if (toRetain.isEmpty()) { parentAssocs.clear(); return; } Iterator<Map.Entry<String, Set<String>>> i = parentAssocs.entrySet().iterator(); StringBuilder groupList = null; while (i.hasNext()) { Map.Entry<String, Set<String>> entry = i.next(); String child = entry.getKey(); if (!toRetain.contains(child)) { if (TenantChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { if (groupList == null) { groupList = new StringBuilder(1024); } else { groupList.setLength(0); } for (String parent : entry.getValue()) { if (groupList.length() > 0) { groupList.append(", "); } groupList.append('\'') .append(TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(parent)) .append('\''); } TenantChainingUserRegistrySynchronizer.logger.debug("Ignoring non-existent member '" + TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(child) + "' in groups {" + groupList.toString() + "}. RunAs user:" + AuthenticationUtil.getRunAsUser()); } i.remove(); } } } public void processGroups(UserRegistry userRegistry, boolean isFullSync, boolean splitTxns) { // If we got back some groups, we have to cross reference them // with the set of known authorities if (isFullSync || !this.groupParentAssocsToDelete.isEmpty() || !this.groupParentAssocsToDelete.isEmpty()) { processGroupSynchInTenantMode(userRegistry, isFullSync, splitTxns); } } private void processGroupSynchInTenantMode(UserRegistry userRegistry, boolean isFullSync, boolean splitTxns) { final Set<String> allZonePersons = newPersonSet(); final Set<String> allZoneGroups = new TreeSet<String>(); final String tenantId = SEIPTenantIntegration.getTenantId(); // Add in current set of known authorities TenantChainingUserRegistrySynchronizer.this.transactionService.getRetryingTransactionHelper() .doInTransaction(new RetryingTransactionCallback<Void>() { public Void execute() throws Throwable { allZonePersons.addAll(TenantChainingUserRegistrySynchronizer.this.authorityService .getAllAuthoritiesInZone(zoneId, AuthorityType.USER)); allZoneGroups.addAll(TenantChainingUserRegistrySynchronizer.this.authorityService .getAllAuthoritiesInZone(zoneId, AuthorityType.GROUP)); return null; } }, true, splitTxns); allZoneGroups.addAll(this.groupsToCreate.keySet()); // Prune our set of authorities according to deletions if (isFullSync) { final Set<String> personDeletionCandidates = newPersonSet(); personDeletionCandidates.addAll(allZonePersons); final Set<String> groupDeletionCandidates = new TreeSet<String>(); groupDeletionCandidates.addAll(allZoneGroups); this.deletionCandidates = new TreeSet<String>(); for (String person : userRegistry.getPersonNames()) { personDeletionCandidates.remove(person); } for (String group : userRegistry.getGroupNames()) { groupDeletionCandidates.remove(group); } this.deletionCandidates = new TreeSet<String>(); this.deletionCandidates.addAll(personDeletionCandidates); this.deletionCandidates.addAll(groupDeletionCandidates); if (allowDeletions) { allZonePersons.removeAll(personDeletionCandidates); allZoneGroups.removeAll(groupDeletionCandidates); } else { if (!personDeletionCandidates.isEmpty()) { TenantChainingUserRegistrySynchronizer.logger.warn( "The following missing users are not being deleted as allowDeletions == false"); for (String person : personDeletionCandidates) { TenantChainingUserRegistrySynchronizer.logger.warn(" " + person); } } if (!groupDeletionCandidates.isEmpty()) { TenantChainingUserRegistrySynchronizer.logger.warn( "The following missing groups are not being deleted as allowDeletions == false"); for (String group : groupDeletionCandidates) { TenantChainingUserRegistrySynchronizer.logger.warn(" " + group); } } // Complete association deletion information by // scanning deleted groups BatchProcessor<String> groupScanner = new BatchProcessor<String>( zone + " Missing Authority Scanning", TenantChainingUserRegistrySynchronizer.this.transactionService .getRetryingTransactionHelper(), this.deletionCandidates, TenantChainingUserRegistrySynchronizer.this.workerThreads, 20, TenantChainingUserRegistrySynchronizer.this.applicationEventPublisher, TenantChainingUserRegistrySynchronizer.logger, TenantChainingUserRegistrySynchronizer.this.loggingInterval); groupScanner.process(new BaseBatchProcessWorker<String>() { @Override public String getIdentifier(String entry) { return entry; } @Override public void process(final String authority) throws Throwable { AuthenticationUtil.runAs(new RunAsWork<Void>() { @Override public Void doWork() throws Exception { proceesInTenantMode(zoneId, authority); return null; } }, SEIPTenantIntegration.getSystemUserByTenantId(tenantId)); } private void proceesInTenantMode(final String zoneId, String authority) { // Disassociate it from this zone, allowing // it to be reclaimed by something further // down the chain TenantChainingUserRegistrySynchronizer.this.authorityService .removeAuthorityFromZones(authority, Collections.singleton(zoneId)); // For groups, remove all members if (AuthorityType.getAuthorityType(authority) != AuthorityType.USER) { String groupShortName = TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(authority); String groupDisplayName = TenantChainingUserRegistrySynchronizer.this.authorityService .getAuthorityDisplayName(authority); NodeDescription dummy = new NodeDescription(groupShortName + " (Deleted)"); PropertyMap dummyProperties = dummy.getProperties(); dummyProperties.put(ContentModel.PROP_AUTHORITY_NAME, authority); if (groupDisplayName != null) { dummyProperties.put(ContentModel.PROP_AUTHORITY_DISPLAY_NAME, groupDisplayName); } updateGroup(dummy, true); } } }, splitTxns); } } // Prune the group associations now that we have complete // information this.groupParentAssocsToCreate.keySet().retainAll(allZoneGroups); logRetainParentAssociations(this.groupParentAssocsToCreate, allZoneGroups); this.finalGroupChildAssocs.keySet().retainAll(allZoneGroups); // Pruning person associations will have to wait until we // have passed over all persons and built up // this set this.allZonePersons = allZonePersons; if (!this.groupParentAssocsToDelete.isEmpty()) { // Create/update the groups and delete parent // associations to be deleted BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>( zone + " Group Creation and Association Deletion", TenantChainingUserRegistrySynchronizer.this.transactionService .getRetryingTransactionHelper(), this.groupParentAssocsToDelete.entrySet(), TenantChainingUserRegistrySynchronizer.this.workerThreads, 20, TenantChainingUserRegistrySynchronizer.this.applicationEventPublisher, TenantChainingUserRegistrySynchronizer.logger, TenantChainingUserRegistrySynchronizer.this.loggingInterval); groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() { public String getIdentifier(Map.Entry<String, Set<String>> entry) { return entry.getKey() + " " + entry.getValue(); } public void process(final Map.Entry<String, Set<String>> entry) throws Throwable { AuthenticationUtil.runAs(new RunAsWork<Void>() { @Override public Void doWork() throws Exception { processInternal(zoneSet, entry.getKey()); return null; } }, SEIPTenantIntegration.getSystemUserByTenantId(tenantId)); } private void processInternal(final Set<String> zoneSet, String child) { String groupDisplayName = Analyzer.this.groupsToCreate.get(child); if (groupDisplayName != null) { String groupShortName = TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(child); if (TenantChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { TenantChainingUserRegistrySynchronizer.logger .debug("Creating group '" + groupShortName + "'"); } // create the group TenantChainingUserRegistrySynchronizer.this.authorityService.createAuthority( AuthorityType.getAuthorityType(child), groupShortName, groupDisplayName, zoneSet); } else { // Maintain association deletions now. The // creations will have to be done later once // we have performed all the deletions in // order to avoid creating cycles maintainAssociationDeletions(child); } } }, splitTxns); } } public void finalizeAssociations(UserRegistry userRegistry, boolean splitTxns) { // First validate the group associations to be created for // potential cycles. Remove any offending association validateGroupParentAssocsToCreate(); // Now go ahead and create the group associations if (!this.groupParentAssocsToCreate.isEmpty()) { BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>( zone + " Group Association Creation", TenantChainingUserRegistrySynchronizer.this.transactionService .getRetryingTransactionHelper(), this.groupParentAssocsToCreate.entrySet(), TenantChainingUserRegistrySynchronizer.this.workerThreads, 20, TenantChainingUserRegistrySynchronizer.this.applicationEventPublisher, TenantChainingUserRegistrySynchronizer.logger, TenantChainingUserRegistrySynchronizer.this.loggingInterval); groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() { public String getIdentifier(Map.Entry<String, Set<String>> entry) { return entry.getKey() + " " + entry.getValue(); } public void process(Map.Entry<String, Set<String>> entry) throws Throwable { final String user = entry.getKey(); AuthenticationUtil.runAs(new RunAsWork<Void>() { @Override public Void doWork() throws Exception { maintainAssociationCreations(user); return null; } }, SEIPTenantIntegration.getSystemUser(user)); } }, splitTxns); } // Remove all the associations we have already dealt with this.personParentAssocsToDelete.keySet().removeAll(this.personsProcessed); // Filter out associations to authorities that simply can't // exist (and log if debugging is enabled) logRetainParentAssociations(this.personParentAssocsToCreate, this.allZonePersons); // Update associations to persons not updated themselves if (!this.personParentAssocsToDelete.isEmpty()) { BatchProcessor<Map.Entry<String, Set<String>>> groupCreator = new BatchProcessor<Map.Entry<String, Set<String>>>( zone + " Person Association", TenantChainingUserRegistrySynchronizer.this.transactionService .getRetryingTransactionHelper(), this.personParentAssocsToDelete.entrySet(), TenantChainingUserRegistrySynchronizer.this.workerThreads, 20, TenantChainingUserRegistrySynchronizer.this.applicationEventPublisher, TenantChainingUserRegistrySynchronizer.logger, TenantChainingUserRegistrySynchronizer.this.loggingInterval); groupCreator.process(new BaseBatchProcessWorker<Map.Entry<String, Set<String>>>() { public String getIdentifier(Map.Entry<String, Set<String>> entry) { return entry.getKey() + " " + entry.getValue(); } public void process(final Map.Entry<String, Set<String>> entry) throws Throwable { final String user = entry.getKey(); AuthenticationUtil.runAs(new RunAsWork<Void>() { @Override public Void doWork() throws Exception { maintainAssociationDeletions(user); maintainAssociationCreations(user); return null; } }, SEIPTenantIntegration.getSystemUser(user)); } }, splitTxns); } } private void maintainAssociationDeletions(String authorityName) { boolean isPerson = AuthorityType.getAuthorityType(authorityName) == AuthorityType.USER; Set<String> parentsToDelete = isPerson ? this.personParentAssocsToDelete.get(authorityName) : this.groupParentAssocsToDelete.get(authorityName); if (parentsToDelete != null && !parentsToDelete.isEmpty()) { for (String parent : parentsToDelete) { if (TenantChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { TenantChainingUserRegistrySynchronizer.logger.debug("Removing '" + TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(authorityName) + "' from group '" + TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(parent) + "'"); } TenantChainingUserRegistrySynchronizer.this.authorityService.removeAuthority(parent, authorityName); } } } private void maintainAssociationCreations(String authorityName) { boolean isPerson = AuthorityType.getAuthorityType(authorityName) == AuthorityType.USER; Set<String> parents = isPerson ? this.personParentAssocsToCreate.get(authorityName) : this.groupParentAssocsToCreate.get(authorityName); if (parents != null && !parents.isEmpty()) { if (TenantChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { for (String groupName : parents) { TenantChainingUserRegistrySynchronizer.logger.debug("Adding '" + TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(authorityName) + "' to group '" + TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(groupName) + "'"); } } try { TenantChainingUserRegistrySynchronizer.this.authorityService.addAuthority(parents, authorityName); } catch (UnknownAuthorityException e) { // Let's force a transaction retry if a parent doesn't // exist. It may be because we are // waiting for another worker thread to create it throw new ConcurrencyFailureException("Forcing batch retry for unknown authority", e); } catch (InvalidNodeRefException e) { // Another thread may have written the node, but it is // not visible to this transaction // See: ALF-5471: 'authorityMigration' patch can report // 'Node does not exist' throw new ConcurrencyFailureException("Forcing batch retry for invalid node", e); } } // Remember that this person's associations have been maintained if (isPerson) { synchronized (this) { this.personsProcessed.add(authorityName); } } } } final Analyzer groupAnalyzer = new Analyzer(lastModifiedMillis); int groupProcessedCount = groupProcessor.process(groupAnalyzer, splitTxns); groupAnalyzer.processGroups(userRegistry, isFullSync, splitTxns); // Process persons and their parent associations lastModifiedMillis = forceUpdate ? -1 : getMostRecentUpdateTime(TenantChainingUserRegistrySynchronizer.PERSON_LAST_MODIFIED_ATTRIBUTE, zoneId, splitTxns); lastModified = lastModifiedMillis == -1 ? null : new Date(lastModifiedMillis); if (TenantChainingUserRegistrySynchronizer.logger.isInfoEnabled()) { if (lastModified == null) { TenantChainingUserRegistrySynchronizer.logger .info("Retrieving all users from user registry '" + zone + "'"); } else { TenantChainingUserRegistrySynchronizer.logger.info( "Retrieving users changed since " + DateFormat.getDateTimeInstance().format(lastModified) + " from user registry '" + zone + "'"); } } final BatchProcessor<NodeDescription> personProcessor = new BatchProcessor<NodeDescription>( zone + " User Creation and Association", this.transactionService.getRetryingTransactionHelper(), userRegistry.getPersons(lastModified), this.workerThreads, 10, this.applicationEventPublisher, TenantChainingUserRegistrySynchronizer.logger, this.loggingInterval); class PersonWorker extends BaseBatchProcessWorker<NodeDescription> { private long latestTime; public PersonWorker(final long latestTime) { this.latestTime = latestTime; } public long getLatestTime() { return this.latestTime; } public String getIdentifier(NodeDescription entry) { return entry.getSourceId(); } public void process(final NodeDescription person) throws Throwable { // Make a mutable copy of the person properties, since they get // written back to by person service HashMap<QName, Serializable> personProperties = new HashMap<QName, Serializable>( person.getProperties()); String personName = (String) personProperties.get(ContentModel.PROP_USERNAME); String ou = (String) personProperties.get(ContentModel.PROP_ORGANIZATION); if (SEIPTenantIntegration.isValidTenant(ou) && !personName.endsWith(ou)) { personName += ("@" + ou); person.getProperties().put(ContentModel.PROP_USERNAME, personName); } final String personFullName = personName; logger.debug("Check user: " + personFullName); String tenantDomain = SEIPTenantIntegration.getTenantId(personFullName); if (tenantDomain != null && !tenantDomain.isEmpty()) { if (!isTenantEnabled(tenantDomain)) { logger.debug("Tenant is missing/disabled for user: " + personFullName); return; } logger.debug("Process user: " + personFullName); AuthenticationUtil.runAs(new RunAsWork<Void>() { @Override public Void doWork() throws Exception { processInTenantMode(personFullName, person); return null; } }, SEIPTenantIntegration.getSystemUserByTenantId(tenantDomain)); } else { logger.debug("Process user: " + personFullName); processInTenantMode(personFullName, person); } } private void processInTenantMode(String personName, NodeDescription person) { HashMap<QName, Serializable> personProperties = person.getProperties(); // Make a mutable copy of the person properties, since they get // written back to by person service Set<String> zones = TenantChainingUserRegistrySynchronizer.this.authorityService .getAuthorityZones(personName); if (zones == null) { // The person did not exist at all if (TenantChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { TenantChainingUserRegistrySynchronizer.logger.debug("Creating user '" + personName + "'"); } TenantChainingUserRegistrySynchronizer.this.personService.createPerson(personProperties, zoneSet); } else if (zones.contains(zoneId)) { // The person already existed in this zone: update the // person if (TenantChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { TenantChainingUserRegistrySynchronizer.logger.debug("Updating user '" + personName + "'"); } TenantChainingUserRegistrySynchronizer.this.personService.setPersonProperties(personName, personProperties, false); } else { // Check whether the user is in any of the authentication // chain zones Set<String> intersection = new TreeSet<String>(zones); intersection.retainAll(allZoneIds); // Check whether the user is in any of the higher priority // authentication chain zones Set<String> visited = new TreeSet<String>(intersection); visited.retainAll(visitedZoneIds); if (visited.size() > 0) { // A person that exists in a different zone with higher // precedence - ignore return; } else if (!allowDeletions || intersection.isEmpty()) { // The person exists, but in a different zone. Either // deletions are disallowed or the zone is // not in the authentication chain. May be due to // upgrade or zone changes. Let's re-zone them if (TenantChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { TenantChainingUserRegistrySynchronizer.logger.warn("Updating user '" + personName + "'. This user will in future be assumed to originate from user registry '" + zone + "'."); } updateAuthorityZones(personName, zones, zoneSet); TenantChainingUserRegistrySynchronizer.this.personService.setPersonProperties(personName, personProperties, false); } else { // The person existed, but in a zone with lower // precedence if (TenantChainingUserRegistrySynchronizer.logger.isWarnEnabled()) { TenantChainingUserRegistrySynchronizer.logger.warn("Recreating occluded user '" + personName + "'. This user was previously created through synchronization with a lower priority user registry."); } TenantChainingUserRegistrySynchronizer.this.personService.deletePerson(personName); TenantChainingUserRegistrySynchronizer.this.personService.createPerson(personProperties, zoneSet); } } // Maintain association deletions and creations in one shot // (safe to do this with persons as we can't // create cycles) groupAnalyzer.maintainAssociationDeletions(personName); groupAnalyzer.maintainAssociationCreations(personName); synchronized (this) { // Maintain the last modified date Date personLastModified = person.getLastModified(); if (personLastModified != null) { this.latestTime = Math.max(this.latestTime, personLastModified.getTime()); } } } } PersonWorker persons = new PersonWorker(lastModifiedMillis); int personProcessedCount = personProcessor.process(persons, splitTxns); // Process those associations to persons who themselves have not been // updated groupAnalyzer.finalizeAssociations(userRegistry, splitTxns); // Only now that the whole tree has been processed is it safe to persist // the last modified dates long latestTime = groupAnalyzer.getLatestTime(); if (latestTime != -1) { setMostRecentUpdateTime(TenantChainingUserRegistrySynchronizer.GROUP_LAST_MODIFIED_ATTRIBUTE, zoneId, latestTime, splitTxns); } latestTime = persons.getLatestTime(); if (latestTime != -1) { setMostRecentUpdateTime(TenantChainingUserRegistrySynchronizer.PERSON_LAST_MODIFIED_ATTRIBUTE, zoneId, latestTime, splitTxns); } // Delete authorities if we have complete information for the zone Set<String> deletionCandidates = groupAnalyzer.getDeletionCandidates(); if (isFullSync && allowDeletions && !deletionCandidates.isEmpty()) { BatchProcessor<String> authorityDeletionProcessor = new BatchProcessor<String>( zone + " Authority Deletion", this.transactionService.getRetryingTransactionHelper(), deletionCandidates, this.workerThreads, 10, this.applicationEventPublisher, TenantChainingUserRegistrySynchronizer.logger, this.loggingInterval); class AuthorityDeleter extends BaseBatchProcessWorker<String> { private int personProcessedCount; private int groupProcessedCount; public int getPersonProcessedCount() { return this.personProcessedCount; } public int getGroupProcessedCount() { return this.groupProcessedCount; } public String getIdentifier(String entry) { return entry; } public void process(String authority) throws Throwable { if (AuthorityType.getAuthorityType(authority) == AuthorityType.USER) { if (TenantChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { TenantChainingUserRegistrySynchronizer.logger .debug("Deleting user '" + authority + "'"); } TenantChainingUserRegistrySynchronizer.this.personService.deletePerson(authority); synchronized (this) { this.personProcessedCount++; } } else { if (TenantChainingUserRegistrySynchronizer.logger.isDebugEnabled()) { TenantChainingUserRegistrySynchronizer.logger.debug("Deleting group '" + TenantChainingUserRegistrySynchronizer.this.authorityService .getShortName(authority) + "'"); } TenantChainingUserRegistrySynchronizer.this.authorityService.deleteAuthority(authority); synchronized (this) { this.groupProcessedCount++; } } } } AuthorityDeleter authorityDeleter = new AuthorityDeleter(); authorityDeletionProcessor.process(authorityDeleter, splitTxns); groupProcessedCount += authorityDeleter.getGroupProcessedCount(); personProcessedCount += authorityDeleter.getPersonProcessedCount(); } // Remember we have visited this zone visitedZoneIds.add(zoneId); if (TenantChainingUserRegistrySynchronizer.logger.isInfoEnabled()) { TenantChainingUserRegistrySynchronizer.logger .info("Finished synchronizing users and groups with user registry '" + zone + "'"); TenantChainingUserRegistrySynchronizer.logger .info(personProcessedCount + " user(s) and " + groupProcessedCount + " group(s) processed"); } }
From source file:op.care.bhp.PnlBHP.java
private CollapsiblePane createCP4(final BHP bhp) { final CollapsiblePane bhpPane = new CollapsiblePane(); bhpPane.setCollapseOnTitleClick(false); ActionListener applyActionListener = new ActionListener() { @Override// w ww. j a v a 2 s . c om public void actionPerformed(ActionEvent actionEvent) { if (bhp.getState() != BHPTools.STATE_OPEN) { return; } if (bhp.getPrescription().isClosed()) { return; } if (BHPTools.isChangeable(bhp)) { outcomeText = null; if (bhp.getNeedsText()) { new DlgYesNo(SYSConst.icon48comment, new Closure() { @Override public void execute(Object o) { if (SYSTools.catchNull(o).isEmpty()) { outcomeText = null; } else { outcomeText = o.toString(); } } }, "nursingrecords.bhp.describe.outcome", null, null); } if (bhp.getNeedsText() && outcomeText == null) { OPDE.getDisplayManager().addSubMessage( new DisplayMessage("nursingrecords.bhp.notext.nooutcome", DisplayMessage.WARNING)); return; } if (bhp.getPrescription().isWeightControlled()) { new DlgYesNo(SYSConst.icon48scales, new Closure() { @Override public void execute(Object o) { if (SYSTools.catchNull(o).isEmpty()) { weight = null; } else { weight = (BigDecimal) o; } } }, "nursingrecords.bhp.weight", null, new Validator<BigDecimal>() { @Override public boolean isValid(String value) { BigDecimal bd = parse(value); return bd != null && bd.compareTo(BigDecimal.ZERO) > 0; } @Override public BigDecimal parse(String text) { return SYSTools.parseDecimal(text); } }); } if (bhp.getPrescription().isWeightControlled() && weight == null) { OPDE.getDisplayManager().addSubMessage(new DisplayMessage( "nursingrecords.bhp.noweight.nosuccess", DisplayMessage.WARNING)); return; } EntityManager em = OPDE.createEM(); try { em.getTransaction().begin(); em.lock(em.merge(resident), LockModeType.OPTIMISTIC); BHP myBHP = em.merge(bhp); em.lock(myBHP, LockModeType.OPTIMISTIC); if (myBHP.isOnDemand()) { em.lock(myBHP.getPrescriptionSchedule(), LockModeType.OPTIMISTIC_FORCE_INCREMENT); em.lock(myBHP.getPrescription(), LockModeType.OPTIMISTIC_FORCE_INCREMENT); } else { em.lock(myBHP.getPrescriptionSchedule(), LockModeType.OPTIMISTIC); em.lock(myBHP.getPrescription(), LockModeType.OPTIMISTIC); } myBHP.setState(BHPTools.STATE_DONE); myBHP.setUser(em.merge(OPDE.getLogin().getUser())); myBHP.setIst(new Date()); myBHP.setiZeit(SYSCalendar.whatTimeIDIs(new Date())); myBHP.setMDate(new Date()); myBHP.setText(outcomeText); Prescription involvedPresciption = null; if (myBHP.shouldBeCalculated()) { MedInventory inventory = TradeFormTools.getInventory4TradeForm(resident, myBHP.getTradeForm()); MedInventoryTools.withdraw(em, em.merge(inventory), myBHP.getDose(), weight, myBHP); // Was the prescription closed during this withdraw ? involvedPresciption = em.find(Prescription.class, myBHP.getPrescription().getID()); } BHP outcomeBHP = null; // add outcome check BHP if necessary if (!myBHP.isOutcomeText() && myBHP.getPrescriptionSchedule().getCheckAfterHours() != null) { outcomeBHP = em.merge(new BHP(myBHP)); mapShift2BHP.get(BHPTools.SHIFT_ON_DEMAND).add(outcomeBHP); } em.getTransaction().commit(); if (myBHP.shouldBeCalculated() && involvedPresciption.isClosed()) { // && reload(); } else if (outcomeBHP != null) { reload(); } else { mapBHP2Pane.put(myBHP, createCP4(myBHP)); int position = mapShift2BHP.get(myBHP.getShift()).indexOf(bhp); mapShift2BHP.get(myBHP.getShift()).remove(position); mapShift2BHP.get(myBHP.getShift()).add(position, myBHP); if (myBHP.isOnDemand()) { // This whole thing here is only to handle the BPHs on Demand // Fix the other BHPs on demand. If not, you will get locking exceptions, // we FORCED INCREMENTED LOCKS on the Schedule and the Prescription. ArrayList<BHP> changeList = new ArrayList<BHP>(); for (BHP bhp : mapShift2BHP.get(BHPTools.SHIFT_ON_DEMAND)) { if (bhp.getPrescription().getID() == myBHP.getPrescription().getID() && bhp.getBHPid() != myBHP.getBHPid()) { bhp.setPrescription(myBHP.getPrescription()); bhp.setPrescriptionSchedule(myBHP.getPrescriptionSchedule()); changeList.add(bhp); } } for (BHP bhp : changeList) { mapBHP2Pane.put(bhp, createCP4(myBHP)); position = mapShift2BHP.get(bhp.getShift()).indexOf(bhp); mapShift2BHP.get(myBHP.getShift()).remove(position); mapShift2BHP.get(myBHP.getShift()).add(position, bhp); } Collections.sort(mapShift2BHP.get(myBHP.getShift()), BHPTools.getOnDemandComparator()); } else { Collections.sort(mapShift2BHP.get(myBHP.getShift())); } mapShift2Pane.put(myBHP.getShift(), createCP4(myBHP.getShift())); buildPanel(false); } } catch (OptimisticLockException ole) { OPDE.warn(ole); if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) { OPDE.getMainframe().emptyFrame(); OPDE.getMainframe().afterLogin(); } OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage()); } catch (RollbackException ole) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) { OPDE.getMainframe().emptyFrame(); OPDE.getMainframe().afterLogin(); } OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage()); } catch (Exception e) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } OPDE.fatal(e); } finally { em.close(); } } else { OPDE.getDisplayManager() .addSubMessage(new DisplayMessage(SYSTools.xx("nursingrecords.bhp.notchangeable"))); } } }; // JPanel titlePanelleft = new JPanel(); // titlePanelleft.setLayout(new BoxLayout(titlePanelleft, BoxLayout.LINE_AXIS)); MedStock stock = mapPrescription2Stock.get(bhp.getPrescription()); if (bhp.hasMed() && stock == null) { stock = MedStockTools .getStockInUse(TradeFormTools.getInventory4TradeForm(resident, bhp.getTradeForm())); mapPrescription2Stock.put(bhp.getPrescription(), stock); } String title; if (bhp.isOutcomeText()) { title = "<html><font size=+1>" + SYSConst.html_italic(SYSTools .left("“" + PrescriptionTools.getShortDescriptionAsCompactText( bhp.getPrescriptionSchedule().getPrescription()), MAX_TEXT_LENGTH) + BHPTools.getScheduleText(bhp.getOutcome4(), "”, ", "")) + " [" + bhp.getPrescriptionSchedule().getCheckAfterHours() + " " + SYSTools.xx("misc.msg.Hour(s)") + "] " + BHPTools.getScheduleText(bhp, ", ", "") + (bhp.getPrescription().isWeightControlled() ? " " + SYSConst.html_16x16_scales_internal + (bhp.isOpen() ? "" : (bhp.getStockTransaction().isEmpty() ? " " : NumberFormat.getNumberInstance() .format(bhp.getStockTransaction().get(0).getWeight()) + "g ")) : "") + (bhp.getUser() != null ? ", <i>" + SYSTools.anonymizeUser(bhp.getUser().getUID()) + "</i>" : "") + "</font></html>"; } else { title = "<html><font size=+1>" + SYSTools.left(PrescriptionTools.getShortDescriptionAsCompactText( bhp.getPrescriptionSchedule().getPrescription()), MAX_TEXT_LENGTH) + (bhp.hasMed() ? ", <b>" + SYSTools.getAsHTML(bhp.getDose()) + " " + DosageFormTools.getUsageText( bhp.getPrescription().getTradeForm().getDosageForm()) + "</b>" : "") + BHPTools.getScheduleText(bhp, ", ", "") + (bhp.getPrescription().isWeightControlled() ? " " + SYSConst.html_16x16_scales_internal + (bhp.isOpen() ? "" : (bhp.getStockTransaction().isEmpty() ? " " : NumberFormat.getNumberInstance() .format(bhp.getStockTransaction().get(0).getWeight()) + "g ")) : "") + (bhp.getUser() != null ? ", <i>" + SYSTools.anonymizeUser(bhp.getUser().getUID()) + "</i>" : "") + "</font></html>"; } DefaultCPTitle cptitle = new DefaultCPTitle(title, OPDE.getAppInfo().isAllowedTo(InternalClassACL.UPDATE, internalClassID) ? applyActionListener : null); JLabel icon1 = new JLabel(BHPTools.getIcon(bhp)); icon1.setOpaque(false); if (!bhp.isOpen()) { icon1.setToolTipText(DateFormat.getDateTimeInstance().format(bhp.getIst())); } JLabel icon2 = new JLabel(BHPTools.getWarningIcon(bhp, stock)); icon2.setOpaque(false); cptitle.getAdditionalIconPanel().add(icon1); cptitle.getAdditionalIconPanel().add(icon2); if (bhp.getPrescription().isClosed()) { JLabel icon3 = new JLabel(SYSConst.icon22stopSign); icon3.setOpaque(false); cptitle.getAdditionalIconPanel().add(icon3); } if (bhp.isOutcomeText()) { JLabel icon4 = new JLabel(SYSConst.icon22comment); icon4.setOpaque(false); cptitle.getAdditionalIconPanel().add(icon4); } if (!bhp.isOutcomeText() && bhp.getPrescriptionSchedule().getCheckAfterHours() != null) { JLabel icon4 = new JLabel(SYSConst.icon22intervalBySecond); icon4.setOpaque(false); cptitle.getAdditionalIconPanel().add(icon4); } if (OPDE.getAppInfo().isAllowedTo(InternalClassACL.UPDATE, internalClassID)) { if (!bhp.getPrescription().isClosed()) { /*** * _ _ _ _ * | |__ | |_ _ __ / \ _ __ _ __ | |_ _ * | '_ \| __| '_ \ / _ \ | '_ \| '_ \| | | | | * | |_) | |_| | | |/ ___ \| |_) | |_) | | |_| | * |_.__/ \__|_| |_/_/ \_\ .__/| .__/|_|\__, | * |_| |_| |___/ */ JButton btnApply = new JButton(SYSConst.icon22apply); btnApply.setPressedIcon(SYSConst.icon22applyPressed); btnApply.setAlignmentX(Component.RIGHT_ALIGNMENT); btnApply.setToolTipText(SYSTools.xx("nursingrecords.bhp.btnApply.tooltip")); btnApply.addActionListener(applyActionListener); btnApply.setContentAreaFilled(false); btnApply.setBorder(null); btnApply.setEnabled(bhp.isOpen() && (!bhp.hasMed() || mapPrescription2Stock.containsKey(bhp.getPrescription()))); cptitle.getRight().add(btnApply); /*** * ____ _ _ * ___ _ __ ___ _ __ / ___|| |_ ___ ___| | __ * / _ \| '_ \ / _ \ '_ \\___ \| __/ _ \ / __| |/ / * | (_) | |_) | __/ | | |___) | || (_) | (__| < * \___/| .__/ \___|_| |_|____/ \__\___/ \___|_|\_\ * |_| */ if (bhp.hasMed() && stock == null && MedInventoryTools.getNextToOpen( TradeFormTools.getInventory4TradeForm(resident, bhp.getTradeForm())) != null) { final JButton btnOpenStock = new JButton(SYSConst.icon22ledGreenOn); btnOpenStock.setPressedIcon(SYSConst.icon22ledGreenOff); btnOpenStock.setAlignmentX(Component.RIGHT_ALIGNMENT); btnOpenStock.setContentAreaFilled(false); btnOpenStock.setBorder(null); btnOpenStock.setToolTipText(SYSTools .toHTMLForScreen(SYSTools.xx("nursingrecords.inventory.stock.btnopen.tooltip"))); btnOpenStock.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { EntityManager em = OPDE.createEM(); try { em.getTransaction().begin(); em.lock(em.merge(resident), LockModeType.OPTIMISTIC); BHP myBHP = em.merge(bhp); em.lock(myBHP, LockModeType.OPTIMISTIC); em.lock(myBHP.getPrescriptionSchedule(), LockModeType.OPTIMISTIC); em.lock(myBHP.getPrescription(), LockModeType.OPTIMISTIC); MedStock myStock = em.merge(MedInventoryTools.openNext( TradeFormTools.getInventory4TradeForm(resident, myBHP.getTradeForm()))); em.lock(myStock, LockModeType.OPTIMISTIC); em.getTransaction().commit(); OPDE.getDisplayManager() .addSubMessage(new DisplayMessage( String.format(SYSTools.xx("newstocks.stock.has.been.opened"), myStock.getID().toString()))); reload(); } catch (OptimisticLockException ole) { OPDE.warn(ole); if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) { OPDE.getMainframe().emptyFrame(); OPDE.getMainframe().afterLogin(); } OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage()); } catch (Exception e) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } OPDE.fatal(e); } finally { em.close(); } } }); cptitle.getRight().add(btnOpenStock); } if (!bhp.isOutcomeText()) { /*** * _ _ ____ __ * | |__ | |_ _ __ | _ \ ___ / _|_ _ ___ ___ * | '_ \| __| '_ \| |_) / _ \ |_| | | / __|/ _ \ * | |_) | |_| | | | _ < __/ _| |_| \__ \ __/ * |_.__/ \__|_| |_|_| \_\___|_| \__,_|___/\___| * */ final JButton btnRefuse = new JButton(SYSConst.icon22cancel); btnRefuse.setPressedIcon(SYSConst.icon22cancelPressed); btnRefuse.setAlignmentX(Component.RIGHT_ALIGNMENT); btnRefuse.setContentAreaFilled(false); btnRefuse.setBorder(null); btnRefuse.setToolTipText( SYSTools.toHTMLForScreen(SYSTools.xx("nursingrecords.bhp.btnRefuse.tooltip"))); btnRefuse.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { if (bhp.getState() != BHPTools.STATE_OPEN) { return; } if (BHPTools.isChangeable(bhp)) { EntityManager em = OPDE.createEM(); try { em.getTransaction().begin(); em.lock(em.merge(resident), LockModeType.OPTIMISTIC); BHP myBHP = em.merge(bhp); em.lock(myBHP, LockModeType.OPTIMISTIC); em.lock(myBHP.getPrescriptionSchedule(), LockModeType.OPTIMISTIC); em.lock(myBHP.getPrescription(), LockModeType.OPTIMISTIC); myBHP.setState(BHPTools.STATE_REFUSED); myBHP.setUser(em.merge(OPDE.getLogin().getUser())); myBHP.setIst(new Date()); myBHP.setiZeit(SYSCalendar.whatTimeIDIs(new Date())); myBHP.setMDate(new Date()); mapBHP2Pane.put(myBHP, createCP4(myBHP)); int position = mapShift2BHP.get(myBHP.getShift()).indexOf(bhp); mapShift2BHP.get(bhp.getShift()).remove(position); mapShift2BHP.get(bhp.getShift()).add(position, myBHP); if (myBHP.isOnDemand()) { Collections.sort(mapShift2BHP.get(myBHP.getShift()), BHPTools.getOnDemandComparator()); } else { Collections.sort(mapShift2BHP.get(myBHP.getShift())); } em.getTransaction().commit(); mapShift2Pane.put(myBHP.getShift(), createCP4(myBHP.getShift())); buildPanel(false); } catch (OptimisticLockException ole) { OPDE.warn(ole); if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) { OPDE.getMainframe().emptyFrame(); OPDE.getMainframe().afterLogin(); } OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage()); } catch (Exception e) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } OPDE.fatal(e); } finally { em.close(); } } else { OPDE.getDisplayManager().addSubMessage( new DisplayMessage(SYSTools.xx("nursingrecords.bhp.notchangeable"))); } } }); btnRefuse.setEnabled(!bhp.isOnDemand() && bhp.isOpen()); cptitle.getRight().add(btnRefuse); /*** * _ _ ____ __ ____ _ _ * | |__ | |_ _ __ | _ \ ___ / _|_ _ ___ ___| _ \(_)___ ___ __ _ _ __ __| | * | '_ \| __| '_ \| |_) / _ \ |_| | | / __|/ _ \ | | | / __|/ __/ _` | '__/ _` | * | |_) | |_| | | | _ < __/ _| |_| \__ \ __/ |_| | \__ \ (_| (_| | | | (_| | * |_.__/ \__|_| |_|_| \_\___|_| \__,_|___/\___|____/|_|___/\___\__,_|_| \__,_| * */ final JButton btnRefuseDiscard = new JButton(SYSConst.icon22deleteall); btnRefuseDiscard.setPressedIcon(SYSConst.icon22deleteallPressed); btnRefuseDiscard.setAlignmentX(Component.RIGHT_ALIGNMENT); btnRefuseDiscard.setContentAreaFilled(false); btnRefuseDiscard.setBorder(null); btnRefuseDiscard.setToolTipText( SYSTools.toHTMLForScreen(SYSTools.xx("nursingrecords.bhp.btnRefuseDiscard.tooltip"))); btnRefuseDiscard.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { if (bhp.getState() != BHPTools.STATE_OPEN) { return; } if (BHPTools.isChangeable(bhp)) { if (bhp.getPrescription().isWeightControlled()) { new DlgYesNo(SYSConst.icon48scales, new Closure() { @Override public void execute(Object o) { if (SYSTools.catchNull(o).isEmpty()) { weight = null; } else { weight = (BigDecimal) o; } } }, "nursingrecords.bhp.weight", null, new Validator<BigDecimal>() { @Override public boolean isValid(String value) { BigDecimal bd = parse(value); return bd != null && bd.compareTo(BigDecimal.ZERO) > 0; } @Override public BigDecimal parse(String text) { return SYSTools.parseDecimal(text); } }); } if (bhp.getPrescription().isWeightControlled() && weight == null) { OPDE.getDisplayManager().addSubMessage(new DisplayMessage( "nursingrecords.bhp.noweight.nosuccess", DisplayMessage.WARNING)); return; } EntityManager em = OPDE.createEM(); try { em.getTransaction().begin(); em.lock(em.merge(resident), LockModeType.OPTIMISTIC); BHP myBHP = em.merge(bhp); em.lock(myBHP, LockModeType.OPTIMISTIC); em.lock(myBHP.getPrescriptionSchedule(), LockModeType.OPTIMISTIC); em.lock(myBHP.getPrescription(), LockModeType.OPTIMISTIC); myBHP.setState(BHPTools.STATE_REFUSED_DISCARDED); myBHP.setUser(em.merge(OPDE.getLogin().getUser())); myBHP.setIst(new Date()); myBHP.setiZeit(SYSCalendar.whatTimeIDIs(new Date())); myBHP.setMDate(new Date()); if (myBHP.shouldBeCalculated()) { MedInventory inventory = TradeFormTools.getInventory4TradeForm(resident, myBHP.getTradeForm()); if (inventory != null) { MedInventoryTools.withdraw(em, em.merge(inventory), myBHP.getDose(), weight, myBHP); } else { OPDE.getDisplayManager().addSubMessage( new DisplayMessage("nursingrecords.bhp.NoInventory")); } } mapBHP2Pane.put(myBHP, createCP4(myBHP)); int position = mapShift2BHP.get(myBHP.getShift()).indexOf(bhp); mapShift2BHP.get(bhp.getShift()).remove(position); mapShift2BHP.get(bhp.getShift()).add(position, myBHP); if (myBHP.isOnDemand()) { Collections.sort(mapShift2BHP.get(myBHP.getShift()), BHPTools.getOnDemandComparator()); } else { Collections.sort(mapShift2BHP.get(myBHP.getShift())); } em.getTransaction().commit(); mapShift2Pane.put(myBHP.getShift(), createCP4(myBHP.getShift())); buildPanel(false); } catch (OptimisticLockException ole) { OPDE.warn(ole); if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) { OPDE.getMainframe().emptyFrame(); OPDE.getMainframe().afterLogin(); } OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage()); } catch (Exception e) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } OPDE.fatal(e); } finally { em.close(); } } else { OPDE.getDisplayManager().addSubMessage( new DisplayMessage(SYSTools.xx("nursingrecords.bhp.notchangeable"))); } } }); btnRefuseDiscard.setEnabled( !bhp.isOnDemand() && bhp.hasMed() && bhp.shouldBeCalculated() && bhp.isOpen()); cptitle.getRight().add(btnRefuseDiscard); } /*** * _ _ _____ _ * | |__ | |_ _ __ | ____|_ __ ___ _ __ | |_ _ _ * | '_ \| __| '_ \| _| | '_ ` _ \| '_ \| __| | | | * | |_) | |_| | | | |___| | | | | | |_) | |_| |_| | * |_.__/ \__|_| |_|_____|_| |_| |_| .__/ \__|\__, | * |_| |___/ */ final JButton btnEmpty = new JButton(SYSConst.icon22empty); btnEmpty.setPressedIcon(SYSConst.icon22emptyPressed); btnEmpty.setAlignmentX(Component.RIGHT_ALIGNMENT); btnEmpty.setContentAreaFilled(false); btnEmpty.setBorder(null); btnEmpty.setToolTipText(SYSTools.xx("nursingrecords.bhp.btnEmpty.tooltip")); btnEmpty.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { if (bhp.getState() == BHPTools.STATE_OPEN) { return; } BHP outcomeBHP = BHPTools.getComment(bhp); if (outcomeBHP != null && !outcomeBHP.isOpen()) { // already commented return; } if (BHPTools.isChangeable(bhp)) { EntityManager em = OPDE.createEM(); try { em.getTransaction().begin(); em.lock(em.merge(resident), LockModeType.OPTIMISTIC); BHP myBHP = em.merge(bhp); em.lock(myBHP, LockModeType.OPTIMISTIC); em.lock(myBHP.getPrescriptionSchedule(), LockModeType.OPTIMISTIC); em.lock(myBHP.getPrescription(), LockModeType.OPTIMISTIC); // the normal BHPs (those assigned to a NursingProcess) are reset to the OPEN state. // TXs are deleted myBHP.setState(BHPTools.STATE_OPEN); myBHP.setUser(null); myBHP.setIst(null); myBHP.setiZeit(null); myBHP.setMDate(new Date()); myBHP.setText(null); if (myBHP.shouldBeCalculated()) { for (MedStockTransaction tx : myBHP.getStockTransaction()) { em.remove(tx); } myBHP.getStockTransaction().clear(); } if (outcomeBHP != null) { BHP myOutcomeBHP = em.merge(outcomeBHP); em.remove(myOutcomeBHP); } if (myBHP.isOnDemand()) { em.remove(myBHP); } em.getTransaction().commit(); if (myBHP.isOnDemand()) { reload(); } else { mapBHP2Pane.put(myBHP, createCP4(myBHP)); int position = mapShift2BHP.get(myBHP.getShift()).indexOf(bhp); mapShift2BHP.get(bhp.getShift()).remove(position); mapShift2BHP.get(bhp.getShift()).add(position, myBHP); if (myBHP.isOnDemand()) { Collections.sort(mapShift2BHP.get(myBHP.getShift()), BHPTools.getOnDemandComparator()); } else { Collections.sort(mapShift2BHP.get(myBHP.getShift())); } mapShift2Pane.put(myBHP.getShift(), createCP4(myBHP.getShift())); buildPanel(false); } } catch (OptimisticLockException ole) { OPDE.warn(ole); if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) { OPDE.getMainframe().emptyFrame(); OPDE.getMainframe().afterLogin(); } OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage()); } catch (Exception e) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } OPDE.fatal(e); } finally { em.close(); } } else { OPDE.getDisplayManager().addSubMessage( new DisplayMessage(SYSTools.xx("nursingrecords.bhp.notchangeable"))); } } }); btnEmpty.setEnabled(!bhp.isOpen()); cptitle.getRight().add(btnEmpty); } /*** * _ _ ___ __ * | |__ | |_ _ __ |_ _|_ __ / _| ___ * | '_ \| __| '_ \ | || '_ \| |_ / _ \ * | |_) | |_| | | || || | | | _| (_) | * |_.__/ \__|_| |_|___|_| |_|_| \___/ * */ final JButton btnInfo = new JButton(SYSConst.icon22info); btnInfo.setPressedIcon(SYSConst.icon22infoPressed); btnInfo.setAlignmentX(Component.RIGHT_ALIGNMENT); btnInfo.setContentAreaFilled(false); btnInfo.setBorder(null); btnInfo.setToolTipText(SYSTools.xx("nursingrecords.bhp.btnInfo.tooltip")); final JTextPane txt = new JTextPane(); txt.setContentType("text/html"); txt.setEditable(false); final JidePopup popupInfo = new JidePopup(); popupInfo.setMovable(false); popupInfo.setContentPane(new JScrollPane(txt)); popupInfo.removeExcludedComponent(txt); popupInfo.setDefaultFocusComponent(txt); btnInfo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { popupInfo.setOwner(btnInfo); if (bhp.isOutcomeText() && !bhp.isOpen()) { txt.setText(SYSTools.toHTML(SYSConst.html_div(bhp.getText()))); } else { txt.setText(SYSTools.toHTML(SYSConst.html_div(bhp.getPrescription().getText()))); } // txt.setText(SYSTools.toHTML(SYSConst.html_div(bhp.getPrescription().getText()))); GUITools.showPopup(popupInfo, SwingConstants.SOUTH_WEST); } }); if (bhp.isOutcomeText() && !bhp.isOpen()) { btnInfo.setEnabled(true); } else { btnInfo.setEnabled(!SYSTools.catchNull(bhp.getPrescription().getText()).isEmpty()); } cptitle.getRight().add(btnInfo); } bhpPane.setTitleLabelComponent(cptitle.getMain()); bhpPane.setSlidingDirection(SwingConstants.SOUTH); final JTextPane contentPane = new JTextPane(); contentPane.setEditable(false); contentPane.setContentType("text/html"); bhpPane.setContentPane(contentPane); bhpPane.setBackground(bhp.getBG()); bhpPane.setForeground(bhp.getFG()); try { bhpPane.setCollapsed(true); } catch (PropertyVetoException e) { OPDE.error(e); } bhpPane.addCollapsiblePaneListener(new CollapsiblePaneAdapter() { @Override public void paneExpanded(CollapsiblePaneEvent collapsiblePaneEvent) { contentPane.setText(SYSTools.toHTML( PrescriptionTools.getPrescriptionAsHTML(bhp.getPrescription(), false, false, true, false))); } }); bhpPane.setHorizontalAlignment(SwingConstants.LEADING); bhpPane.setOpaque(false); return bhpPane; }