/* * Copyright 2013 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES 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.openntf.domino.impl; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import lotus.domino.NotesException; import lotus.domino.local.NotesBase; import org.openntf.domino.Base; import org.openntf.domino.BaseImpl; import org.openntf.domino.Database; import org.openntf.domino.Directory; import org.openntf.domino.Document; import org.openntf.domino.MIMEEntity; import org.openntf.domino.NotesCalendar; import org.openntf.domino.Outline; import org.openntf.domino.PropertyBroker; import org.openntf.domino.Replication; import org.openntf.domino.RichTextItem; import org.openntf.domino.RichTextNavigator; import org.openntf.domino.RichTextParagraphStyle; import org.openntf.domino.Session; import org.openntf.domino.View; import org.openntf.domino.exceptions.UndefinedDelegateTypeException; import org.openntf.domino.ext.Session.Fixes; import org.openntf.domino.helpers.DatabaseMetaData; import org.openntf.domino.types.FactorySchema; import org.openntf.domino.utils.DominoUtils; // TODO: Auto-generated Javadoc /** * The Enum Factory. */ public class WrapperFactory extends BaseImpl<lotus.domino.Base> implements org.openntf.domino.WrapperFactory { /** this is the holder for all other object that need to be recycled **/ private static ThreadLocal<DominoReferenceCache> referenceCache = new ThreadLocal<DominoReferenceCache>() { @Override protected DominoReferenceCache initialValue() { return new DominoReferenceCache(); } }; protected static final int LAST_WRAPPED_DOC_CACHE_SIZE = 10; // we store the last 10 wrapped documents (these documents are logged) private static ThreadLocal<String[]> lastWrappedDocs = new ThreadLocal<String[]>() { @Override protected String[] initialValue() { return new String[LAST_WRAPPED_DOC_CACHE_SIZE]; } }; /** * Tracks the document for logging * * @param string * * @param lotusDoc * @param parent */ private void trackDoc(final Document doc, final String string) { String[] arr = lastWrappedDocs.get(); System.arraycopy(arr, 0, arr, 1, arr.length - 1); // shift right by one arr[0] = doc.toString().concat(string); } private void clearLWDCache() { lastWrappedDocs.get()[0] = null; } @Override public String[] getLastWrappedDocsInThread() { String[] arr = lastWrappedDocs.get(); for (int i = 0; i < LAST_WRAPPED_DOC_CACHE_SIZE; i++) { if (arr[i] == null) { String[] ret = new String[i]; System.arraycopy(arr, 0, ret, 0, i); return ret; } } return arr; } private long clearCaches() { long result = 0; // call gc once before processing the queues System.gc(); try { //give the gc some ms (not too much, we do not want to delay HTTP-Requests! Thread.sleep(1); } catch (InterruptedException e) { // and ignore this //DominoUtils.handleException(e); } // TODO: Recycle all? //System.out.println("Online objects: " + Factory.getActiveObjectCount()); DominoReferenceCache rc = referenceCache.get(); result = rc.processQueue(null, null); result += rc.finishThreadSafes(); //System.out.println("Online objects: " + Factory.getActiveObjectCount()); clearLWDCache(); return result; } /** The Constant log_. */ private static final Logger log_ = Logger.getLogger(WrapperFactory.class.getName()); // /** // * This function enqueus the reference and lotus, so that it will get recycled. This works by observing the life time of "reference" and // * calling recycle it neccessary // * // * @param reference // * @param lotus // * @return // */ // public void observe(final Object reference, final lotus.domino.Base lotus) { // if (reference != null && lotus != null) { // lotusObjects.put(0L, reference, lotus); // Factory.countLotus(); // } // } // -- Factory methods @Override @SuppressWarnings("rawtypes") public <T extends Base, D extends lotus.domino.Base, P extends Base> // T fromLotus(final D lotus, final FactorySchema<T, D, P> schema, final P parent) { return fromLotus(lotus, schema, parent, null, referenceCache.get()); } @SuppressWarnings({ "rawtypes", "unchecked" }) protected <T extends Base, D extends lotus.domino.Base, P extends Base> // T fromLotus(final D lotus, final FactorySchema<T, D, P> schema, P parent, final Collection<lotus.domino.Base> prevent_recycling, final DominoReferenceCache referenceCache) { if (lotus == null) { return null; } if (lotus instanceof Base) { if (log_.isLoggable(Level.FINE)) log_.log(Level.FINE, "Returning an already OpenNTF object..."); return (T) lotus; } if (!(lotus instanceof NotesBase)) { // RPr: what do we if we don't get a wrappable object at all. This is a programming error, so throw exception throw new UndefinedDelegateTypeException("Cannot wrap " + lotus.getClass().getName()); } if (parent == null) { try { parent = (P) findParent(lotus); } catch (NotesException e) { DominoUtils.handleException(e); } } if (parent == null) throw new UndefinedDelegateTypeException("Cannot find parent for a " + lotus.getClass().getName()); // 1) These objects are not cached and returned immediately. Recycle is done inside if (lotus instanceof lotus.domino.Name // These objects are encapsulated || lotus instanceof lotus.domino.DateRange // || lotus instanceof lotus.domino.DateTime) { // return (T) wrapLotusObject(lotus, parent); } return (T) fromLotusObject(lotus, parent, prevent_recycling, referenceCache); } @Override @SuppressWarnings({ "rawtypes", "unchecked" }) public <T extends Base, D extends lotus.domino.Base, P extends Base> // Collection<T> fromLotus(final Collection<?> lotusColl, final FactorySchema<T, D, P> schema, final P parent) { DominoReferenceCache rc = referenceCache.get(); Collection<lotus.domino.Base> prevent_recycling = getContainingNotesObjects(null, lotusColl); Collection<T> result = new ArrayList<T>(lotusColl.size()); if (!lotusColl.isEmpty()) { for (Object lotus : lotusColl) { if (lotus instanceof lotus.domino.Base) { result.add(fromLotus((D) lotus, schema, parent, prevent_recycling, rc)); } } } return result; } @Override @SuppressWarnings({ "rawtypes", "unchecked" }) public <T extends Base, D extends lotus.domino.Base, P extends Base> // Vector<T> fromLotusAsVector(final Collection<?> lotusColl, final FactorySchema<T, D, P> schema, final P parent) { DominoReferenceCache rc = referenceCache.get(); Collection<lotus.domino.Base> prevent_recycling = getContainingNotesObjects(null, lotusColl); Vector<T> result = new Vector<T>(lotusColl.size()); if (!lotusColl.isEmpty()) { for (Object lotus : lotusColl) { if (lotus instanceof lotus.domino.Base) { result.add(fromLotus((D) lotus, schema, parent, prevent_recycling, rc)); } } } return result; } /** * Returns a collection that contains all lotus objects that should be wrapped in this task * * @param objects * @param obj * @return */ private List<lotus.domino.Base> getContainingNotesObjects(List<lotus.domino.Base> objects, final Object obj) { if (obj instanceof lotus.domino.Base) { if (objects == null) objects = new ArrayList<lotus.domino.Base>(); objects.add((lotus.domino.Base) obj); } else if (obj instanceof Iterable) { for (Object o : (Iterable<?>) obj) { objects = getContainingNotesObjects(objects, o); } } return objects; } // --- others /** * Wraps & caches all lotus object except Names, DateTimes, Sessions, Documents * * @param lotus * @param prevent_recycling * the cpp_ids that must not get recycled during this task. Attention. For performance reasons you should not use slot 0 and * 1 in the array * @param parent * @return */ protected Base<?> fromLotusObject(final lotus.domino.Base lotus, final Base<?> parent, final Collection<lotus.domino.Base> prevent_recycling, final DominoReferenceCache cache) { if (lotus == null) { return null; } // RPr: Query the cache. The current lotus object might be enqued, so that it gets recycled in the next step Base<?> result = cache.get(lotus); if (result == null) { // RPr: If the result is null, we can be sure, that there is no element in our cache map. // this happens if no one holds a strong reference to the wrapper. As "get" does some cleanup // action, we must ensure, that we do not recycle the CURRENT (and parent) element in the next step result = wrapLotusObject(lotus, parent); if (result == null && lotus != null) { throw new IllegalStateException("Could not wrap an object of type" + lotus.getClass().getName()); } if (result instanceof Document) trackDoc((Document) result, ""); cache.processQueue(lotus, prevent_recycling); // recycle all elements but not the current ones cache.put(lotus, result); if (lotus instanceof lotus.domino.Session // || lotus instanceof lotus.domino.AgentContext) { // these are never recycled by default. If you create your own session, you have to recycle it after use // or setNoRecycle to "false" cache.setNoRecycle(lotus, true); // System.out.println("DEBUG: Wrapping a new Session with object id: " + System.identityHashCode(lotus)); } } return result; } @Override public void recacheLotusObject(final lotus.domino.Base newLotus, final Base<?> wrapper, final Base<?> parent) { if (wrapper instanceof Document) trackDoc((Document) wrapper, "/recache"); DominoReferenceCache rc = referenceCache.get(); rc.processQueue(newLotus, null); // recycle all elements but not the current ones // RPr: What happens here: // You recace the same lotus objects for different wrappers // This is something that should not happen unless you use deferred objects. Assume you are retrieving // // Document doc1 = db.getDocumentByID(0xF376, true); // Document doc2 = db.getDocumentByID(0xF376, true); // so doc1 != doc2, but both are refering to the same delegate. // Recycle of the delegate will occur if ONE of the two wrappers is gc'ed org.openntf.domino.impl.Base<?, ?, ?> oldWrapper = (org.openntf.domino.impl.Base<?, ?, ?>) rc.put(newLotus, wrapper); if (oldWrapper != null && oldWrapper != wrapper) { org.openntf.domino.impl.Base<?, ?, ?> implWrapper = (org.openntf.domino.impl.Base<?, ?, ?>) wrapper; if ((implWrapper.siblingWrapper_ == null)) { // wrapper is new and not yet linked, so build a chain of all so that // they are refering to each other implWrapper.linkToExisting(oldWrapper); } } } @Override public void setNoRecycle(final Base<?> base, final boolean value) { referenceCache.get().setNoRecycle(toLotus(base), value); } /** * Helper for fromLotusObject, so you can overwrite this * * @param lotus * @param parent * can be null, except for {@link DirectoryNavigator}, {@link MIMEEntity}, {@link MIMEHeader}, {@link NotesCalendarEntry}, * {@link NotesCalendarNotice}, {@link Replication}, {@link ReplicationEntry}, {@link RichTextDoclink}, * {@link RichTextNavigator}, {@link RichTextRange}, {@link RichTextSection}, {@link RichTextTab}, {@link RichTextTable} * @param cpp * @return * @throws NotesException */ protected Base<?> wrapLotusObject(final lotus.domino.Base lotus, final Base<?> parent) { long cpp = 0; // most frequently used objects if (lotus instanceof lotus.domino.Name) { if (((Session) parent).isFixEnabled(Fixes.ODA_NAMES)) return new org.openntf.domino.impl.NameODA((lotus.domino.Name) lotus, (Session) parent); return new org.openntf.domino.impl.Name((lotus.domino.Name) lotus, (Session) parent); } if (lotus instanceof lotus.domino.DateRange) { return new org.openntf.domino.impl.DateRange((lotus.domino.DateRange) lotus, (Session) parent); } if (lotus instanceof lotus.domino.DateTime) { return new org.openntf.domino.impl.DateTime((lotus.domino.DateTime) lotus, (Session) parent); } if (lotus instanceof lotus.domino.ViewEntry) { return new org.openntf.domino.impl.ViewEntry((lotus.domino.ViewEntry) lotus, (View) parent); } if (lotus instanceof lotus.domino.RichTextItem) { // items & richtextitems are used very often. return new org.openntf.domino.impl.RichTextItem((lotus.domino.RichTextItem) lotus, (Document) parent); } if (lotus instanceof lotus.domino.Item) { // check for Item must be behind RichtextItem return new org.openntf.domino.impl.Item((lotus.domino.Item) lotus, (Document) parent); } if (lotus instanceof lotus.domino.Document) { //trackDoc((lotus.domino.Document) lotus, (Database) parent); return new org.openntf.domino.impl.Document((lotus.domino.Document) lotus, (Database) parent); } if (lotus instanceof lotus.domino.MIMEEntity) { return new org.openntf.domino.impl.MIMEEntity((lotus.domino.MIMEEntity) lotus, (Document) parent); } if (lotus instanceof lotus.domino.MIMEHeader) { return new org.openntf.domino.impl.MIMEHeader((lotus.domino.MIMEHeader) lotus, (MIMEEntity) parent); } if (lotus instanceof lotus.domino.DocumentCollection) { return new org.openntf.domino.impl.DocumentCollection((lotus.domino.DocumentCollection) lotus, (Database) parent); } // Standard objects if (lotus instanceof lotus.domino.ACL) { return new org.openntf.domino.impl.ACL((lotus.domino.ACL) lotus, (Database) parent); } if (lotus instanceof lotus.domino.ACLEntry) { return new org.openntf.domino.impl.ACLEntry((lotus.domino.ACLEntry) lotus, (org.openntf.domino.ACL) parent); } if (lotus instanceof lotus.domino.AdministrationProcess) { return new org.openntf.domino.impl.AdministrationProcess((lotus.domino.AdministrationProcess) lotus, (Session) parent); } if (lotus instanceof lotus.domino.Agent) { return new org.openntf.domino.impl.Agent((lotus.domino.Agent) lotus, (Database) parent); } if (lotus instanceof lotus.domino.AgentContext) { return new org.openntf.domino.impl.AgentContext((lotus.domino.AgentContext) lotus, (Session) parent); } if (lotus instanceof lotus.domino.ColorObject) { return new org.openntf.domino.impl.ColorObject((lotus.domino.ColorObject) lotus, (Session) parent); } if (lotus instanceof lotus.domino.Database) { return new org.openntf.domino.impl.Database((lotus.domino.Database) lotus, (Session) parent); } if (lotus instanceof lotus.domino.DbDirectory) { return new org.openntf.domino.impl.DbDirectory((lotus.domino.DbDirectory) lotus, (Session) parent); } if (lotus instanceof lotus.domino.Directory) { return new org.openntf.domino.impl.Directory((lotus.domino.Directory) lotus, (Session) parent); } if (lotus instanceof lotus.domino.DirectoryNavigator) { return new org.openntf.domino.impl.DirectoryNavigator((lotus.domino.DirectoryNavigator) lotus, (Directory) parent); } if (lotus instanceof lotus.domino.DxlExporter) { return new org.openntf.domino.impl.DxlExporter((lotus.domino.DxlExporter) lotus, (Session) parent); } if (lotus instanceof lotus.domino.DxlImporter) { return new org.openntf.domino.impl.DxlImporter((lotus.domino.DxlImporter) lotus, (Session) parent); } if (lotus instanceof lotus.domino.EmbeddedObject) { return new org.openntf.domino.impl.EmbeddedObject((lotus.domino.EmbeddedObject) lotus, (Document) parent); } if (lotus instanceof lotus.domino.Form) { return new org.openntf.domino.impl.Form((lotus.domino.Form) lotus, (Database) parent); } if (lotus instanceof lotus.domino.International) { return new org.openntf.domino.impl.International((lotus.domino.International) lotus, (Session) parent); } if (lotus instanceof lotus.domino.Log) { return new org.openntf.domino.impl.Log((lotus.domino.Log) lotus, (Session) parent); } if (lotus instanceof lotus.domino.Newsletter) { return new org.openntf.domino.impl.Newsletter((lotus.domino.Newsletter) lotus, (Session) parent); } if (lotus instanceof lotus.domino.NoteCollection) { return new org.openntf.domino.impl.NoteCollection((lotus.domino.NoteCollection) lotus, (org.openntf.domino.Database) parent); } if (lotus instanceof lotus.domino.NotesCalendar) { return new org.openntf.domino.impl.NotesCalendar((lotus.domino.NotesCalendar) lotus, (Session) parent); } if (lotus instanceof lotus.domino.NotesCalendarEntry) { return new org.openntf.domino.impl.NotesCalendarEntry((lotus.domino.NotesCalendarEntry) lotus, (NotesCalendar) parent, this, cpp); } if (lotus instanceof lotus.domino.NotesCalendarNotice) { return new org.openntf.domino.impl.NotesCalendarNotice((lotus.domino.NotesCalendarNotice) lotus, (NotesCalendar) parent, this, cpp); } if (lotus instanceof lotus.domino.NotesProperty) { return new org.openntf.domino.impl.NotesProperty((lotus.domino.NotesProperty) lotus, (PropertyBroker) parent); } if (lotus instanceof lotus.domino.Outline) { return new org.openntf.domino.impl.Outline((lotus.domino.Outline) lotus, (Database) parent); } if (lotus instanceof lotus.domino.OutlineEntry) { return new org.openntf.domino.impl.OutlineEntry((lotus.domino.OutlineEntry) lotus, (Outline) parent); } if (lotus instanceof lotus.domino.PropertyBroker) { return new org.openntf.domino.impl.PropertyBroker((lotus.domino.PropertyBroker) lotus, (Session) parent); } if (lotus instanceof lotus.domino.Registration) { return new org.openntf.domino.impl.Registration((lotus.domino.Registration) lotus, (Session) parent); } if (lotus instanceof lotus.domino.Replication) { return new org.openntf.domino.impl.Replication((lotus.domino.Replication) lotus, (Database) parent); } if (lotus instanceof lotus.domino.ReplicationEntry) { return new org.openntf.domino.impl.ReplicationEntry((lotus.domino.ReplicationEntry) lotus, (Replication) parent); } if (lotus instanceof lotus.domino.RichTextDoclink) { return new org.openntf.domino.impl.RichTextDoclink((lotus.domino.RichTextDoclink) lotus, (RichTextItem) parent); } if (lotus instanceof lotus.domino.RichTextNavigator) { return new org.openntf.domino.impl.RichTextNavigator((lotus.domino.RichTextNavigator) lotus, (RichTextItem) parent); } if (lotus instanceof lotus.domino.RichTextParagraphStyle) { return new org.openntf.domino.impl.RichTextParagraphStyle((lotus.domino.RichTextParagraphStyle) lotus, (Session) parent, this, cpp); } if (lotus instanceof lotus.domino.RichTextRange) { return new org.openntf.domino.impl.RichTextRange((lotus.domino.RichTextRange) lotus, (RichTextItem) parent); } if (lotus instanceof lotus.domino.RichTextSection) { return new org.openntf.domino.impl.RichTextSection((lotus.domino.RichTextSection) lotus, (RichTextNavigator) parent); } if (lotus instanceof lotus.domino.RichTextStyle) { return new org.openntf.domino.impl.RichTextStyle((lotus.domino.RichTextStyle) lotus, (Session) parent); } if (lotus instanceof lotus.domino.RichTextTab) { return new org.openntf.domino.impl.RichTextTab((lotus.domino.RichTextTab) lotus, (RichTextParagraphStyle) parent); } if (lotus instanceof lotus.domino.RichTextTable) { return new org.openntf.domino.impl.RichTextTable((lotus.domino.RichTextTable) lotus, (RichTextItem) parent); } if (lotus instanceof lotus.domino.Stream) { return new org.openntf.domino.impl.Stream((lotus.domino.Stream) lotus, (Session) parent); } if (lotus instanceof lotus.domino.View) { return new org.openntf.domino.impl.View((lotus.domino.View) lotus, (org.openntf.domino.Database) parent); } if (lotus instanceof lotus.domino.ViewColumn) { return new org.openntf.domino.impl.ViewColumn((lotus.domino.ViewColumn) lotus, (org.openntf.domino.View) parent); } if (lotus instanceof lotus.domino.ViewEntryCollection) { return new org.openntf.domino.impl.ViewEntryCollection((lotus.domino.ViewEntryCollection) lotus, (org.openntf.domino.View) parent); } if (lotus instanceof lotus.domino.ViewNavigator) { return new org.openntf.domino.impl.ViewNavigator((lotus.domino.ViewNavigator) lotus, (org.openntf.domino.View) parent); } if (lotus instanceof lotus.domino.Session) { return new org.openntf.domino.impl.Session((lotus.domino.Session) lotus, this); } throw new UndefinedDelegateTypeException(lotus == null ? "null" : lotus.getClass().getName()); } /** * Find the parent object for the given lotus * * @param lotus * @return * @throws NotesException */ protected Base<?> findParent(final lotus.domino.Base lotus) throws NotesException { if (lotus instanceof lotus.domino.Name) { return fromLotus(((lotus.domino.Name) lotus).getParent(), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.DateRange) { return fromLotus(((lotus.domino.DateRange) lotus).getParent(), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.DateTime) { return fromLotus(((lotus.domino.DateTime) lotus).getParent(), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.ViewEntry) { return fromLotus(org.openntf.domino.impl.ViewEntry.getParentView((lotus.domino.ViewEntry) lotus), View.SCHEMA, null); } if (lotus instanceof lotus.domino.RichTextItem) { return fromLotus(((lotus.domino.RichTextItem) lotus).getParent(), Document.SCHEMA, null); } if (lotus instanceof lotus.domino.Item) { return fromLotus(((lotus.domino.Item) lotus).getParent(), Document.SCHEMA, null); } if (lotus instanceof lotus.domino.Document) { return fromLotus(((lotus.domino.Document) lotus).getParentDatabase(), Database.SCHEMA, null); } if (lotus instanceof lotus.domino.DocumentCollection) { return fromLotus(((lotus.domino.DocumentCollection) lotus).getParent(), Database.SCHEMA, null); } if (lotus instanceof lotus.domino.ACL) { return fromLotus(((lotus.domino.ACL) lotus).getParent(), Database.SCHEMA, null); } if (lotus instanceof lotus.domino.ACLEntry) { return fromLotus(((lotus.domino.ACLEntry) lotus).getParent(), ACL.SCHEMA, null); } if (lotus instanceof lotus.domino.AdministrationProcess) { return fromLotus(((lotus.domino.AdministrationProcess) lotus).getParent(), Session.SCHEMA, this); } if (lotus instanceof lotus.domino.Agent) { return fromLotus(((lotus.domino.Agent) lotus).getParent(), Database.SCHEMA, null); } if (lotus instanceof lotus.domino.AgentContext) { return fromLotus(org.openntf.domino.impl.Base.getSession(lotus), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.ColorObject) { return fromLotus(org.openntf.domino.impl.Base.getSession(lotus), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.Database) { return fromLotus(((lotus.domino.Database) lotus).getParent(), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.DbDirectory) { return fromLotus(((lotus.domino.DbDirectory) lotus).getParent(), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.Directory) { return fromLotus(org.openntf.domino.impl.Base.getSession(lotus), Session.SCHEMA, null); } // it is not possible to find the parent object of these objects // if (lotus instanceof lotus.domino.DirectoryNavigator) { // return fromLotus(((lotus.domino.DirectoryNavigator) lotus).getParent(), (Directory) parent, null); // } // if (lotus instanceof lotus.domino.MIMEEntity) { // return fromLotus(((lotus.domino.MIMEEntity) lotus).getParent(), Document.SCHEMA, null); // } // if (lotus instanceof lotus.domino.MIMEHeader) { // return fromLotus(((lotus.domino.MIMEHeader) lotus).getParent(), MIMEEntity.SCHEMA, null); // } // if (lotus instanceof lotus.domino.NotesCalendarEntry) { // return fromLotus(((lotus.domino.NotesCalendarEntry) lotus).getParent(), NotesCalendar.SCHEMA, null); // } // if (lotus instanceof lotus.domino.NotesCalendarNotice) { // return fromLotus(((lotus.domino.NotesCalendarNotice) lotus).getParent(), NotesCalendar.SCHEMA, null); // } // if (lotus instanceof lotus.domino.NotesProperty) { // return fromLotus(((lotus.domino.NotesProperty) lotus).getParent(), PropertyBroker.SCHEMA, null); // } // if (lotus instanceof lotus.domino.Replication) { // return fromLotus(((lotus.domino.Replication) lotus).getParent(), Database.SCHEMA, null); // } // if (lotus instanceof lotus.domino.ReplicationEntry) { // return fromLotus(((lotus.domino.ReplicationEntry) lotus).getParent(), Replication.SCHEMA, null); // } // if (lotus instanceof lotus.domino.RichTextDoclink) { // return fromLotus(((lotus.domino.RichTextDoclink) lotus).getParent(), RichTextItem.SCHEMA, null); // } // if (lotus instanceof lotus.domino.RichTextNavigator) { // return fromLotus(((lotus.domino.RichTextNavigator) lotus).getParent(), RichTextItem.SCHEMA, null); // } // if (lotus instanceof lotus.domino.RichTextRange) { // return fromLotus(((lotus.domino.RichTextRange) lotus).getParent(), RichTextItem.SCHEMA, null); // } // if (lotus instanceof lotus.domino.RichTextSection) { // return fromLotus(((lotus.domino.RichTextSection) lotus).getParent(), RichTextNavigator.SCHEMA, null); // } // if (lotus instanceof lotus.domino.RichTextTab) { // return fromLotus(((lotus.domino.RichTextTab) lotus).getParent(), RichTextParagraphStyle.SCHEMA, null); // } // if (lotus instanceof lotus.domino.RichTextTable) { // return fromLotus(((lotus.domino.RichTextTable) lotus).getParent(), RichTextItem.SCHEMA, null); // } if (lotus instanceof lotus.domino.DxlExporter) { return fromLotus(org.openntf.domino.impl.Base.getSession(lotus), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.DxlImporter) { return fromLotus(org.openntf.domino.impl.Base.getSession(lotus), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.EmbeddedObject) { return fromLotus(((lotus.domino.EmbeddedObject) lotus).getParent().getParent(), Document.SCHEMA, null); } if (lotus instanceof lotus.domino.Form) { return fromLotus(((lotus.domino.Form) lotus).getParent(), Database.SCHEMA, null); } if (lotus instanceof lotus.domino.International) { return fromLotus(((lotus.domino.International) lotus).getParent(), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.Log) { return fromLotus(((lotus.domino.Log) lotus).getParent(), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.Newsletter) { return fromLotus(((lotus.domino.Newsletter) lotus).getParent(), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.NoteCollection) { return fromLotus(((lotus.domino.NoteCollection) lotus).getParent(), Database.SCHEMA, null); } if (lotus instanceof lotus.domino.NotesCalendar) { return fromLotus(org.openntf.domino.impl.Base.getSession(lotus), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.Outline) { return fromLotus(((lotus.domino.Outline) lotus).getParentDatabase(), Database.SCHEMA, null); } if (lotus instanceof lotus.domino.OutlineEntry) { return fromLotus(((lotus.domino.OutlineEntry) lotus).getParent(), Outline.SCHEMA, null); } if (lotus instanceof lotus.domino.PropertyBroker) { return fromLotus(org.openntf.domino.impl.Base.getSession(lotus), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.Registration) { return fromLotus(((lotus.domino.Registration) lotus).getParent(), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.RichTextParagraphStyle) { return fromLotus(org.openntf.domino.impl.Base.getSession(lotus), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.RichTextStyle) { return fromLotus(((lotus.domino.RichTextStyle) lotus).getParent(), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.Stream) { return fromLotus(org.openntf.domino.impl.Base.getSession(lotus), Session.SCHEMA, null); } if (lotus instanceof lotus.domino.View) { return fromLotus(((lotus.domino.View) lotus).getParent(), Database.SCHEMA, null); } if (lotus instanceof lotus.domino.ViewColumn) { return fromLotus(((lotus.domino.ViewColumn) lotus).getParent(), View.SCHEMA, null); } if (lotus instanceof lotus.domino.ViewEntryCollection) { return fromLotus(((lotus.domino.ViewEntryCollection) lotus).getParent(), View.SCHEMA, null); } if (lotus instanceof lotus.domino.ViewNavigator) { return fromLotus(((lotus.domino.ViewNavigator) lotus).getParentView(), View.SCHEMA, null); } if (lotus instanceof lotus.domino.Session) { return this; } throw new UnsupportedOperationException("You must specify a valid parent when creating a " + lotus.getClass().getName()); } @Override public void recycle() { clearCaches(); } @SuppressWarnings("unchecked") @Override public Vector<Object> wrapColumnValues(final Collection<?> values, final Session session) { if (values == null) return null; if (values instanceof Vector) { for (Object val : values) { if (!(val instanceof Number) && !(val instanceof String) && !(val instanceof Date)) { return wrapColumnValues(values, session, getContainingNotesObjects(null, values), referenceCache.get()); } } return (Vector<Object>) values; // values is a vector that contains only Number/String/Date-values. So it is safe } return wrapColumnValues(values, session, getContainingNotesObjects(null, values), referenceCache.get()); } /** * Internal method * * @param values * @param session * @param prevent_recycling * @param referenceCache * @return */ @SuppressWarnings({ "unchecked", "rawtypes" }) protected Vector<Object> wrapColumnValues(final Collection<?> values, final Session session, final Collection<lotus.domino.Base> prevent_recycling, final DominoReferenceCache referenceCache) { if (values == null) { return null; } int i = 0; java.util.Vector<Object> result = new java.util.Vector<Object>(); for (Object value : values) { if (value == null) { result.add(null); } else if (value instanceof lotus.domino.DateTime) { Object wrapped = null; try { wrapped = fromLotus((lotus.domino.DateTime) value, DateTime.SCHEMA, session, prevent_recycling, referenceCache); } catch (Throwable t) { if (t instanceof NotesException) { String text = ((NotesException) t).text; System.out.println("Unable to wrap a DateTime found in Vector member " + i + " of " + values.size() + " because " + text); try { lotus.domino.DateTime dt = (lotus.domino.DateTime) value; String gmttime = dt.getGMTTime(); System.out.println("GMTTime: " + gmttime); } catch (Exception e) { } } } if (wrapped == null) { result.add(""); } else { result.add(wrapped); } } else if (value instanceof lotus.domino.DateRange) { result.add(fromLotus((lotus.domino.DateRange) value, (FactorySchema) null, session, prevent_recycling, referenceCache)); } else if (value instanceof Collection) { result.add(wrapColumnValues((Collection<?>) value, session, prevent_recycling, referenceCache)); } else { result.add(value); } i++; } return result; } @Override public <T extends lotus.domino.Base> T toLotus(final T base) { return org.openntf.domino.impl.Base.toLotus(base); } //----------- create @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public <T extends Base, P extends Base> T create(final FactorySchema<T, ?, P> schema, final P parent, final Object metaData) { if (schema == Item.SCHEMA) { return (T) new org.openntf.domino.impl.Item((Document) parent, (String) metaData); // item name } if (schema == DateTime.SCHEMA) { return (T) new org.openntf.domino.impl.DateTime((Session) parent); // no metadata } if (schema == DateRange.SCHEMA) { return (T) new org.openntf.domino.impl.DateRange((Session) parent); // no metadata } if (schema == Name.SCHEMA) { String name = null; String lang = null; if (metaData instanceof String) name = (String) metaData; else { String[] sArr = (String[]) metaData; name = sArr[0]; lang = sArr[1]; } if (((Session) parent).isFixEnabled(Fixes.ODA_NAMES)) return (T) new org.openntf.domino.impl.NameODA((Session) parent, name, lang); return (T) ((Session) parent).createNameNonODA(name); } if (schema == Document.SCHEMA) { return (T) new org.openntf.domino.impl.Document((Database) parent, metaData); // noteID/UNID } if (schema == Database.SCHEMA) { return (T) new org.openntf.domino.impl.Database((Session) parent, (DatabaseMetaData) metaData); // DB-Metadata for closed DBs } throw new IllegalArgumentException("Cannot create object by " + schema.getClass()); } @SuppressWarnings("rawtypes") @Override public void recycle(final Vector vec) { org.openntf.domino.impl.Base.s_recycle(vec); } @Override public void recycle(final lotus.domino.Base obj) { org.openntf.domino.impl.Base.s_recycle(obj); } @Override public boolean isDead() { return false; } }