1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "precompiled_sd.hxx"
25 
26 #include "ConfigurationClassifier.hxx"
27 
28 #include "framework/FrameworkHelper.hxx"
29 
30 using namespace ::com::sun::star;
31 using namespace ::com::sun::star::uno;
32 using namespace ::com::sun::star::drawing::framework;
33 using ::rtl::OUString;
34 
35 #undef VERBOSE
36 //#define VERBOSE 2
37 
38 
39 namespace sd { namespace framework {
40 
41 ConfigurationClassifier::ConfigurationClassifier (
42     const Reference<XConfiguration>& rxConfiguration1,
43     const Reference<XConfiguration>& rxConfiguration2)
44     : mxConfiguration1(rxConfiguration1),
45       mxConfiguration2(rxConfiguration2),
46       maC1minusC2(),
47       maC2minusC1(),
48       maC1andC2()
49 {
50 }
51 
52 
53 
54 
55 bool ConfigurationClassifier::Partition (void)
56 {
57     maC1minusC2.clear();
58     maC2minusC1.clear();
59     maC1andC2.clear();
60 
61     PartitionResources(
62         mxConfiguration1->getResources(NULL, OUString(), AnchorBindingMode_DIRECT),
63         mxConfiguration2->getResources(NULL, OUString(), AnchorBindingMode_DIRECT));
64 
65     return !maC1minusC2.empty() || !maC2minusC1.empty();
66 }
67 
68 
69 
70 
71 const ConfigurationClassifier::ResourceIdVector& ConfigurationClassifier::GetC1minusC2 (void) const
72 {
73     return maC1minusC2;
74 }
75 
76 
77 
78 
79 const ConfigurationClassifier::ResourceIdVector& ConfigurationClassifier::GetC2minusC1 (void) const
80 {
81     return maC2minusC1;
82 }
83 
84 
85 
86 const ConfigurationClassifier::ResourceIdVector& ConfigurationClassifier::GetC1andC2 (void) const
87 {
88     return maC1andC2;
89 }
90 
91 
92 void ConfigurationClassifier::PartitionResources (
93     const ::com::sun::star::uno::Sequence<Reference<XResourceId> >& rS1,
94     const ::com::sun::star::uno::Sequence<Reference<XResourceId> >& rS2)
95 {
96     ResourceIdVector aC1minusC2;
97     ResourceIdVector aC2minusC1;
98     ResourceIdVector aC1andC2;
99 
100     // Classify the resources in the configurations that are not bound to
101     // other resources.
102     ClassifyResources(
103         rS1,
104         rS2,
105         aC1minusC2,
106         aC2minusC1,
107         aC1andC2);
108 
109 #if defined VERBOSE && VERBOSE >= 2
110     OSL_TRACE("copying resource ids to C1-C2\r");
111 #endif
112     CopyResources(aC1minusC2, mxConfiguration1, maC1minusC2);
113 #if defined VERBOSE && VERBOSE >= 2
114     OSL_TRACE("copying resource ids to C2-C1\r");
115 #endif
116     CopyResources(aC2minusC1, mxConfiguration2, maC2minusC1);
117 
118     // Process the unique resources that belong to both configurations.
119     ResourceIdVector::const_iterator iResource;
120     for (iResource=aC1andC2.begin(); iResource!=aC1andC2.end(); ++iResource)
121     {
122         maC1andC2.push_back(*iResource);
123         PartitionResources(
124             mxConfiguration1->getResources(*iResource, OUString(), AnchorBindingMode_DIRECT),
125             mxConfiguration2->getResources(*iResource, OUString(), AnchorBindingMode_DIRECT));
126     }
127 }
128 
129 
130 
131 
132 void ConfigurationClassifier::ClassifyResources (
133     const ::com::sun::star::uno::Sequence<Reference<XResourceId> >& rS1,
134     const ::com::sun::star::uno::Sequence<Reference<XResourceId> >& rS2,
135     ResourceIdVector& rS1minusS2,
136     ResourceIdVector& rS2minusS1,
137     ResourceIdVector& rS1andS2)
138 {
139     // Get arrays from the sequences for faster iteration.
140     const Reference<XResourceId>* aA1 = rS1.getConstArray();
141     const Reference<XResourceId>* aA2 = rS2.getConstArray();
142     sal_Int32 nL1 (rS1.getLength());
143     sal_Int32 nL2 (rS2.getLength());
144 
145     // Find all elements in rS1 and place them in rS1minusS2 or rS1andS2
146     // depending on whether they are in rS2 or not.
147     for (sal_Int32 i=0; i<nL1; ++i)
148     {
149         bool bFound (false);
150         for (sal_Int32 j=0; j<nL2 && !bFound; ++j)
151             if (aA1[i]->getResourceURL().equals(aA2[j]->getResourceURL()))
152                 bFound = true;
153 
154         if (bFound)
155             rS1andS2.push_back(aA1[i]);
156         else
157             rS1minusS2.push_back(aA1[i]);
158     }
159 
160     // Find all elements in rS2 that are not in rS1.  The elements that are
161     // in both rS1 and rS2 have been handled above and are therefore ignored
162     // here.
163     for (sal_Int32 j=0; j<nL2; ++j)
164     {
165         bool bFound (false);
166         for (sal_Int32 i=0; i<nL1 && !bFound; ++i)
167             if (aA2[j]->getResourceURL().equals(aA1[i]->getResourceURL()))
168                 bFound = true;
169 
170         if ( ! bFound)
171             rS2minusS1.push_back(aA2[j]);
172     }
173 }
174 
175 
176 
177 
178 void ConfigurationClassifier::CopyResources (
179     const ResourceIdVector& rSource,
180     const Reference<XConfiguration>& rxConfiguration,
181     ResourceIdVector& rTarget)
182 {
183     // Copy all resources bound to the ones in aC1minusC2Unique to rC1minusC2.
184     ResourceIdVector::const_iterator iResource (rSource.begin());
185     ResourceIdVector::const_iterator iEnd(rSource.end());
186     for ( ; iResource!=iEnd; ++iResource)
187     {
188         const Sequence<Reference<XResourceId> > aBoundResources (
189             rxConfiguration->getResources(
190                 *iResource,
191                 OUString(),
192                 AnchorBindingMode_INDIRECT));
193         const sal_Int32 nL (aBoundResources.getLength());
194 
195         rTarget.reserve(rTarget.size() + 1 + nL);
196         rTarget.push_back(*iResource);
197 
198 #if defined VERBOSE && VERBOSE >= 2
199         OSL_TRACE("    copying %s\r",
200             OUStringToOString(FrameworkHelper::ResourceIdToString(*iResource),
201                 RTL_TEXTENCODING_UTF8).getStr());
202 #endif
203 
204         const Reference<XResourceId>* aA = aBoundResources.getConstArray();
205         for (sal_Int32 i=0; i<nL; ++i)
206         {
207             rTarget.push_back(aA[i]);
208 #if defined VERBOSE && VERBOSE >= 2
209             OSL_TRACE("    copying %s\r",
210                 OUStringToOString(FrameworkHelper::ResourceIdToString(aA[i]),
211                     RTL_TEXTENCODING_UTF8).getStr());
212 #endif
213         }
214     }
215 }
216 
217 
218 void ConfigurationClassifier::TraceResourceIdVector (
219     const sal_Char* pMessage,
220     const ResourceIdVector& rResources) const
221 {
222 
223     OSL_TRACE(pMessage);
224     ResourceIdVector::const_iterator iResource;
225     for (iResource=rResources.begin(); iResource!=rResources.end(); ++iResource)
226     {
227         OUString sResource (FrameworkHelper::ResourceIdToString(*iResource));
228         OSL_TRACE("    %s\r",
229             OUStringToOString(sResource, RTL_TEXTENCODING_UTF8).getStr());
230     }
231 }
232 
233 
234 } } // end of namespace sd::framework
235